Я пытаюсь создать вектор как контейнер Vector.
Затем заявил:
Vector< A> Avector.
При выделении памяти выдается ошибка компиляции, что у A нет конструктора по умолчанию.
Я написал следующий код для выделения памяти.
char *pBuffer = (char*) malloc(size*sizeof(T));
T *array;
for(int i = 0; i < size; i++)
{
(array+i) = new(pBuffer + i) T;
}
return array;
T — это переменная шаблона.
Ошибка связана с тем, что при размещении новых я использую конструктор по умолчанию для T, а я не написал конструктор по умолчанию для A.
Я хочу знать, есть ли способ, чтобы распределение памяти не зависело от сигнатуры конструктора.
В C ++ вызов new
делает две вещи:
Это базовая конструктивная особенность C ++ как языка, pt 2 был добавлен, чтобы преодолеть malloc
Поведение просто выделения памяти.
Короче говоря, вы не можете изменить это поведение.
Это не распределение памяти, которое зависит от сигнатуры конструктора. Это инициализация это делает.
Даже в вашем примере распределение выполняется malloc
без вызова какого-либо конструктора. Это инициализация (выполняется путем размещения новой), которая требует использования конструктора.
Нет способа инициализировать пользовательский объект без вызова его конструктора.
Однако то, что вы можете сделать, по крайней мере в C ++ 11, — это поместить ваш код в функцию, которая принимает аргументы, необходимые вам для конструктора, в качестве rvalue-ссылок и передает их вызову конструктора в Placement-New. , Таким образом, вызывающая сторона вашей функции должна передать правильные аргументы. Если аргументы не передаются, вызывается конструктор по умолчанию.
Это на самом деле метод, используемый emplace
функции нового std::vector
:
template< class... Args >
void emplace_back( Args&&... args );
Это шаблон с переменным числом аргументов, поэтому возможно любое количество аргументов (ноль или более). Rvalue-ссылки используются для их получения, и внутри реализации вам придется вызывать конструктор, используя std::forward
чтобы аргументы передавались как есть:
(array+i) = new (pBuffer + i) T(std::forward<Params>(args)...);
Таким образом, это все еще требует использования конструктора, но он оставляет за вызывающей стороной право выбора конструктора (путем выбора аргументов). Если конструктор по умолчанию недоступен, вызывающая сторона просто должна предоставить аргументы, необходимые для вызова конструктора не по умолчанию.