Копировать конструктор, вызываемый несколько раз при выполнении push_back в векторе [дубликат]

Не совсем верно. Локальные переменные должны быть инициализированы только в качестве ссылки. Локальная переменная может быть оставлена ​​неинициализированной, если ее не ссылать. Например:

  int x;  // Valid int y;  println ("y =" + y);  // Недействительно, так как значение y никогда не было назначено  
6
задан 0x499602D2 4 November 2014 в 17:49
поделиться

5 ответов

Что происходит:

  1. x вставлен через push_back. Возникает одна копия: вновь созданный элемент инициализируется аргументом. my_int берется как ноль, потому что конструктор по умолчанию x s инициализировал его так.
  2. Второй элемент - 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 Поскольку существует конструктор, созданный пользователем.

10
ответ дан Columbo 16 August 2018 в 02:23
поделиться

Вы правы в предположении, что дополнительный вызов конструктора копирования происходит из внутренней реструктуризации вектора.

Подробнее см. в этом ответе: https://stackoverflow.com/a / 10368636/3708904

Или этот ответ по причине необходимости создания копии: https://stackoverflow.com/a/11166959/3708904

3
ответ дан Community 16 August 2018 в 02:23
поделиться

Когда размер вектора увеличивается со вторым push_back, существующее содержимое вектора должно быть скопировано в новый буфер. Чтобы проверить вывод myints.capacity() после первого push_back, он должен быть 1.

3
ответ дан Mark Ransom 16 August 2018 в 02:23
поделиться
  • 1
    Несвязанный: почему этот же пример дает вывод 0 1 0 вместо 0 0 1 в коде OP? – 0x499602D2 4 November 2014 в 17:57
  • 2
    @ 0x499602D2 возможно, что реализация копирует элемент push_back в новый буфер, прежде чем он копирует старый буфер. – Mark Ransom 4 November 2014 в 17:59

Это зависит от того, сколько памяти зарезервировано для объекта типа std::vector. Похоже, что когда push_back был впервые выполнен, выделено память только для одного элемента. Когда был вызван второй раз push_back, память была перераспределена для резервирования памяти для второго элемента. В этом случае элемент, который уже находится в векторе, копируется в новом месте. И затем добавляется второй элемент.

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

vector<Myint> myints;
myints.reserve( 2 );
3
ответ дан Vlad from Moscow 16 August 2018 в 02:23
поделиться
3
ответ дан Community 6 September 2018 в 01:41
поделиться