Почему не делают станд.:: элементам вектора нужен конструктор по умолчанию?

И как я могу записать свой собственный класс массива для не необходимости в конструкторе по умолчанию для его элементов? Прямо сейчас, когда я делаю новое [] для выделения места, мне нужен конструктор по умолчанию.

станд.:: вектор не делает.

Как они делают это волшебство?

25
задан Dan 4 March 2010 в 05:39
поделиться

3 ответа

std::vector не нуждается в конструкторе по умолчанию, потому что он никогда его не использует. Каждый раз, когда ему нужно создать элемент, он делает это с помощью конструктора copy, потому что каждый раз ему есть что копировать: либо существующий элемент вектора, либо элемент, который вы сами предоставили для копирования через параметр метода (явно или неявно, полагаясь на аргумент по умолчанию)

Вы можете написать подобный класс точно так же: каждый раз, когда вам нужно создать новый элемент в массиве, требуйте от пользователя предоставить элемент для копирования. В этом случае создание исходного элемента становится обязанностью пользователя.

Каждый раз, когда кажется, что std::vector "требует" от вас конструктор по умолчанию, это просто означает, что где-то вы полагались на аргумент по умолчанию какого-то из методов vectorа, то есть это вы пытались сконструировать элемент по умолчанию, а не вектор. Сам вектор, опять же, никогда не будет пытаться конструировать элементы по умолчанию.

Чтобы избежать требования конструктора по умолчанию при выделении памяти, стандартная библиотека выделяет raw uninitialized блок памяти и затем немедленно копирует-конструирует новые элементы в этом raw блоке памяти (чего не может сделать new[]). Эта функциональность заключена в классе std::allocator. Вы можете использовать std::allocator и в своем коде, то есть "магия" будет доступна и вам.

Примечание: Вышесказанное относится к версии спецификации языка C++ до C++11. C++11 многое изменил. И эти изменения действительно создают ситуации, в которых std::vector может использовать конструкторы по умолчанию внутри.

Также стоит отметить, что даже оригинальная спецификация C++98 позволяла реализациям использовать перегрузку функций вместо аргументов по умолчанию для реализации интерфейса стандартной библиотеки. Это означает, что формально возможна корректная C++98 реализация std::vector, которая использует конструкторы по умолчанию внутри.

30
ответ дан 28 November 2019 в 20:53
поделиться

std :: vector требует, чтобы у элемента был конструктор по умолчанию, только если вы используете его каким-либо образом для чего требуется конструктор по умолчанию. Таким образом, этот код (украденный из удаленного ответа) не будет компилироваться, потому что X не имеет ctor по умолчанию:

#include <vector>

struct X
{
  X(int) {}
};

int main(void)
{
  std::vector<X> x(1); // vector of length 1, second argument defaults to X() !!
  return 0;
}

Но если вы напишете main вместо этого:

int main(void)
{
  std::vector<X> x; // make empty vector
  x.push_back(X(1));
  return 0;
}

Тогда все работает нормально.

11
ответ дан 28 November 2019 в 20:53
поделиться

Вы можете выделить блок байтов, а затем использовать размещение new , чтобы создать новый экземпляр T (ваш параметрический тип) через конструктор копирования (конечно, не конструктор по умолчанию), когда новые элементы помещаются обратно в вектор. Это не позволит создать «вектор из N инициализированных по умолчанию Ts» (который может создать std :: vector - вот почему требуется, чтобы T имел конструктор по умолчанию для этой цели), но вы можете сделать векторы, которые начинаются пустыми, и на них можно наложить T.

7
ответ дан 28 November 2019 в 20:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: