std :: vector и copy конструкторы

vector v;
X x;
v.push_back(x); v.push_back(x); v.push_back(x);

Почему этот код вызывает конструктор копирования классаX 6 раз? (с использованием g ++ 4.7.2 STL)

Пожалуйста, я'я хотел бы знать этоточно что происходит под капотом с этим конкретным STL.

 Arthur15 нояб. 2012 г., 11:58
попробуй позвонитьv.reserve(3), это должно уменьшить количество вызовов для копирования конструктора.
 Kiril Kirov15 нояб. 2012 г., 11:56
Это'Реализация определена. Стандарт ничего не говорит об этом, насколько я знаю.
 Kiril Kirov15 нояб. 2012 г., 11:54
Возможно, из-за некоторой перестановки (все элементы вектора должны находиться в непрерывном блоке памяти)
 Cartesius0015 нояб. 2012 г., 11:55
@KirilKirov Да, этоопределенно прав, но яхотелось бы точно знать, что происходит под капотом.

Ответы на вопрос(4)

std::vector реализован с использованием массива удвоения (см .:http://en.wikipedia.org/wiki/Dynamic_array) и это вызывает примерно2 * N раз конструктор копирования.

Например, дляN = 100,000 это вызывает конструктор копирования231,071 раз. Как уже указывалось, количество перераспределений может быть уменьшено путем вызова.v.reserve()

 Cartesius0015 нояб. 2012 г., 12:22
@Angew, я считаю, только gcc 'с реализацией. Смотри вопрос.
 Angew15 нояб. 2012 г., 12:21
"правильный ответ" в том, чтотвой компиляторРеализация std :: vector реализован с использованием массива удвоения. Стандарт не требует такой вещи.
 Stefano Falasca21 июл. 2015 г., 16:28
если размер вектора удваивается каждый раз, когда он становится слишком маленьким, вы подвергаетесь примерно log (N) вызовам конструктора копирования, а не 2 * N
Решение Вопроса

x сpush_back()в конечном итоге память перераспределяется, чтобы освободить место для нового элемента. Уже вставленные элементы должны быть скопированы с помощью конструктора копирования.X(const X&)

Если вы вставите

v.reserve(3);

Перераспределение предотвращается как минимум в течение первых трехpush_back()и, как следствие, будет только три вызоваX(const X&)

 Cartesius0015 нояб. 2012 г., 12:16
В общем тоПравильно, но я предоставил немного более точный ответ.

чтобы создать пространство в векторе перед рукой, чтобы ускорить добавление элементов к вектору и предотвратить это.

 const_ref15 нояб. 2012 г., 12:14
Вы правы. Виноват
 emartel15 нояб. 2012 г., 12:11
resize фактически создаст новые объекты, поэтому вызовет конструктор по умолчанию для 3 новых объектов. push_back добавит вновь созданные объекты в конец списка, и у него будет 6 элементов в его векторе. Запас это то, что ему нужно здесь.

До первого push_back емкость вектора (количество элементов, помещающихся в выделенном им пространстве) равна 0. Поэтому, когда вы делаете первый push_back, он выделяет пространство для 1 элемента и вызывает конструктор копирования (первый вызов) ,

Так что теперь емкость равна единице, и вы говорите ей добавить еще один предмет. Таким образом, он должен выделить больше места, в этом случае, место для еще одного элемента и скопировать исходные элементы в новое пространство (2-й вызов). Второй push_back снова вызывает конструктор копирования (третий вызов).

Теперь у вас есть емкость 2 и сказать ему, чтобы добавить еще один элемент. Таким образом, он должен выделить больше места и скопировать элементы в новое пространство (4-й и 5-й вызовы). Затем третий push_back снова вызывает конструктор копирования (шестой вызов).

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

Ваш ответ на вопрос