У меня есть тривиальный распределитель:
// alloc.h
#include <cstdlib>
#include <new>
#include <iostream>
template <class T>
struct Mallocator {
typedef T value_type;
Mallocator() {
std::cout << "default ctor is called" << std::endl;
}
template <class U> Mallocator(const Mallocator<U>&) {
std::cout << "copy ctor is called" << std::endl;
}
T* allocate(std::size_t n) {
std::cout << "Mallocator::allocate(size_t n) is called, n = " << n << " ";
if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc();
if(T *p = static_cast<T*>(std::malloc(n*sizeof(T)))) {
std::cout << "return p = " << std::hex << (uintptr_t)p << std::dec << std::endl;
return p;
}
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t n) {
std::cout << "Mallocator::deallocate(T *p, size_t n) is called, p = " << std::hex << (uintptr_t)p << std::dec << " n = " << n << std::endl;
std::free(p);
}
};
template <class T, class U>
bool operator==(const Mallocator<T>&, const Mallocator<U>&) { return true; }
template <class T, class U>
bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { return false; }
А это код клиента (используется только один из A
, B
, C
):
#include "alloc.h"
#include <vector>
#include <iostream>
using namespace std;
int main() {
Mallocator<int> a;
cout << "---instantiate---" << endl;
// vector<int, Mallocator<int>> v(a); // A
vector<int, Mallocator<int>> v{Mallocator<int>(a)}; // B
// vector<int, Mallocator<int>> v(Mallocator<int>(a)); // C
cout << "---push_back(1)---" << endl;
v.push_back(1);
cout << "---push_back(2)---" << endl;
v.push_back(2);
cout << "---push_back(3)---" << endl;
v.push_back(3);
cout << "---push_back(4)---" << endl;
v.push_back(4);
cout << "---push_back(5)---" << endl;
v.push_back(5);
cout << "---exiting---" << endl;
}
Вывод, независимо от того, используется ли A
или B
, всегда такой:
default ctor is called
---instantiate---
---push_back(1)---
// omitted for brevity..
Мой вопрос:
(1) если присутствует A
, то распределитель создается только один раз, это понятно. Но когда вместо A
присутствует B
, по-видимому, конструктор копирования Mallocator
вызывается в B
, но вывод не отражает этого. Почему?
(2) Если присутствует B
, какой конструктор std::vector
вызывается? В этом справочнике единственный конструктор, принимающий список инициализаторов, не т выглядит так. И если я использую C
вместо B
, он не скомпилируется, и сообщение об ошибке clang++ не поможет.
Эйдт: Я знаю, что этот распределитель тривиален, но суть этого вопроса не в этом.
Код «alloc.h» взят из здесь, в конце страницы.
Mallocator<int>(a)
. 17.08.2017Mallocator(const Mallocator&) = default;
. Стандарт требует наличия как шаблона конструктора преобразования, так и обычного конструктора копирования. Пример cppreference не включает явное объявление конструктора копирования, потому что неявно объявленный конструктор отлично справляется со своей задачей. 19.08.2017