Не совсем верно. Локальные переменные должны быть инициализированы только в качестве ссылки. Локальная переменная может быть оставлена неинициализированной, если ее не ссылать. Например:
int x; // Valid int y; println ("y =" + y); // Недействительно, так как значение y никогда не было назначено
Что происходит:
x
вставлен через push_back
. Возникает одна копия: вновь созданный элемент инициализируется аргументом. my_int
берется как ноль, потому что конструктор по умолчанию x
s инициализировал его так. push_back
'd; Вектор должен перераспределить память, так как была достигнута внутренняя емкость . Поскольку конструктор перемещения неявно определен для Myint
1, выбран конструктор копирования; Первый элемент копируется во вновь выделенную память (его my_int
все еще ноль ... поэтому конструктор копирования снова показывает my_int
как 0
), а затем x
копируется для инициализации второго элемента (как в случае с первый в шаге 1). На этот раз x
задано значение my_int
, и это говорит нам вывод конструктора копирования. Таким образом, общий объем вызовов - три. Это может варьироваться от одной реализации к другой, поскольку первоначальная емкость может отличаться. Тем не менее, два вызова являются минимальными.
Вы можете уменьшить количество копий за счет резервирования большего объема памяти, то есть увеличить емкость векторов, чтобы перераспределение стало ненужным:
myints.reserve(2); // Now two elements can be inserted without reallocation.
Кроме того, вы можете высвободить копии при вставке следующим образом:
myints.emplace_back(0);
Этот «emplaces» новый элемент - emplace_back
является вариационным шаблоном и поэтому может принимать произвольное количество аргументов, которое оно затем пересылает - без копий или движений - в конструктор элементов.
1 Поскольку существует конструктор, созданный пользователем.
Вы правы в предположении, что дополнительный вызов конструктора копирования происходит из внутренней реструктуризации вектора.
Подробнее см. в этом ответе: https://stackoverflow.com/a / 10368636/3708904
Или этот ответ по причине необходимости создания копии: https://stackoverflow.com/a/11166959/3708904
Когда размер вектора увеличивается со вторым push_back
, существующее содержимое вектора должно быть скопировано в новый буфер. Чтобы проверить вывод myints.capacity()
после первого push_back
, он должен быть 1
.
0 1 0
вместо 0 0 1
в коде OP?
– 0x499602D2
4 November 2014 в 17:57
push_back
в новый буфер, прежде чем он копирует старый буфер.
– Mark Ransom
4 November 2014 в 17:59
Это зависит от того, сколько памяти зарезервировано для объекта типа std::vector
. Похоже, что когда push_back
был впервые выполнен, выделено память только для одного элемента. Когда был вызван второй раз push_back
, память была перераспределена для резервирования памяти для второго элемента. В этом случае элемент, который уже находится в векторе, копируется в новом месте. И затем добавляется второй элемент.
Вы можете зарезервировать достаточно памяти самостоятельно, чтобы избежать второго вызова конструктора копирования:
vector<Myint> myints;
myints.reserve( 2 );