Почему элементам std :: vector не нужен конструктор по умолчанию? - PullRequest
25 голосов
/ 04 марта 2010

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

std :: vector not.

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

Ответы [ 3 ]

29 голосов
/ 04 марта 2010

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

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

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

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

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

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

11 голосов
/ 04 марта 2010

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;
}

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

7 голосов
/ 04 марта 2010

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

...