С++: автоматическое перераспределение векторов вызывает конструкторы копирования? Почему?

Я читаю Учебник по С++, 3-е изд. (Липпман и Лажуа), и в нем говорится, что когда вектор необходимо перераспределить, чтобы освободить место для дополнительных элементов, добавленных с помощью push_back(), элементы копируются в новое пространство, а затем деструктор вызывается для старых элементов. Я не понимаю, зачем это нужно - почему нельзя просто копировать данные побитно? Я предполагаю, что ответ связан с динамическим распределением памяти, но моя текущая цепочка рассуждений заключается в том, что даже если векторные элементы обрабатывают динамическую память, данные, фактически хранящиеся в элементах, будут указателями, а это означает, что побитовое копирование сохранит место, на которое они указывают. к и не будет представлять никаких проблем. Я вижу, как перераспределение динамически выделенной памяти, на которую указывают элементы, может быть проблемой, поскольку это приведет к аннулированию указателей, но, насколько я могу судить, у векторного перераспределения нет причин для этого.

Может ли кто-нибудь дать мне простой пример класса, который не следует перемещать по крупицам?


person user1476176    schedule 23.06.2012    source источник
comment
На ум приходит сценарий, когда конструктор/деструктор регистрирует/отменяет регистрацию адреса класса с родительским объектом.   -  person ta.speot.is    schedule 23.06.2012
comment
На ум приходит сценарий, в котором тип не является тривиально копируемым.   -  person K-ballo    schedule 23.06.2012
comment
На ta.spot.is есть хороший пример, хотя я бы не стал называть каждый реестр объектов родителем. Отдельно некоторые классы могут хранить указатели на свои собственные элементы данных — например, для моделирования некоторого модального состояния, говоря, что некоторые будущие операции теперь должны влиять на этот конкретный член, или иметь итератор во внутреннем векторе.   -  person Tony Delroy    schedule 23.06.2012
comment
Обратите внимание, что вы можете написать свой класс, используя идиому указателя на реализацию, чтобы в основном сократить конструктор копирования до побитовой ситуации, или просто хранить интеллектуальные указатели, если вы столкнетесь с реальной жизненной ситуацией, когда это произойдет.   -  person djechlin    schedule 23.06.2012
comment
Конечно, есть вероятность, что ваши умные указатели не будут счастливы быть скопированными...   -  person Managu    schedule 23.06.2012
comment
Они, наконец, исправили это, введя семантику перемещения в последних версиях языка. Но меня также интересует убедительный пример того, почему все это копирование ценности было необходимо в первую очередь.   -  person Oleg Kolosov    schedule 23.06.2012


Ответы (2)


Вот, наверное, самый простой (но довольно надуманный) пример:

class foo
{
  int i;
  int* pi; // always points to i
};

Здесь конструктор копирования будет поддерживать инвариант, согласно которому pi указывает на i. Сам компилятор не смог бы выяснить эту связь самостоятельно, поэтому необходимо вызвать конструктор копирования.

person jjlin    schedule 23.06.2012

Может ли кто-нибудь дать мне простой пример класса, который не следует перемещать по крупицам?

По стандарту выполнение memcpy для любого класса, который не является подходит POD в C++03 (или тривиально копируемый в C++11). memcpying не-POD (или нетривиально копируемые) вызывает неопределенное поведение; поэтому фактически должен использоваться конструктор копии (или в C++11, перемещения).

Таким образом, std::vector сам по себе применяется, так как это не тип POD (и в C++11 его нельзя копировать тривиально).

person Nicol Bolas    schedule 23.06.2012