Что происходит, когда объект остается неинициализированным во время конструктора копирования или в операторе присваивания?

#c

#c

Вопрос:

Предположим, у меня есть векторный объект в качестве одного из атрибутов, и я не инициализирую его в конструкторе копирования, что произойдет тогда? Кроме того, если я сделаю это для любого другого объекта, у которого нет конструктора по умолчанию, что тогда произойдет?

Комментарии:

1. Это должно быть то же самое, вам не нужно явно копировать элементы vector в другой, эту работу должна выполнять копия конструктора по умолчанию.

2. @dexterous_stranger Если вы скопируете a std::vector , у вас серьезные проблемы.

3. Если вы определяете конструктор копирования, компилятор не создает его для вас и не пытается переопределить ваш код. Итак, если объект vector не скопирован вами в конструкторе копирования, он не копируется, и новый объект vector будет пустым

4. @TC — конструктор по умолчанию предназначен только для побитового копирования. Итак, когда вы не упоминаете конструктор копирования, будет вызван конструктор по умолчанию.

5. @dexterous_stranger Нет, это не только побитовое копирование.

Ответ №1:

Предположим, у меня есть векторный объект в качестве одного из атрибутов, и я не инициализирую его в конструкторе копирования, что произойдет тогда?

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

Также, если я сделаю это для любого другого объекта, у которого нет конструктора по умолчанию, что тогда произойдет?

Ваша программа не будет запущена. Более конкретно, компилятор выдаст сообщение об ошибке, указывающее, что вы пытаетесь (или неявно пытаетесь) использовать несуществующий или недоступный конструктор этого объекта. Попробуйте убедиться в этом сами ;) .

Способ (читай: не совсем способ) обойти эти типы объектов — это динамически распределять их, то есть использовать std::unique_ptr s из них. Таким образом, вы могли бы отложить их построение, когда были получены необходимые аргументы. Однако лучший способ, если вы можете и должны, — это увеличить или обернуть класс объекта, чтобы включить семантику перемещения. С помощью семантики перемещения вы могли бы устранить проблему «отложенного построения, потому что у меня еще нет необходимых аргументов». Конструктор по умолчанию оставил бы состояние объекта неинициализированным, то есть непригодным для использования, но повторно инициализируемым с помощью конструктора перемещения / копирования. Отличным примером для этого является std::thread .

Ответ №2:

Конструкторы копирования ничем не отличаются от других конструкторов. Члены класса, которые явно не инициализированы внутри конструктора, инициализируются по умолчанию, что означает, что члены типа class создаются по умолчанию, каждый элемент членов массива инициализируется по умолчанию, и в противном случае инициализация не выполняется. Если у члена класса нет конструктора по умолчанию, и вы не инициализируете его в конструкторе копирования, компилятор сообщит об ошибке.

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

Что касается присваивания, члены класса, которым не назначено, просто сохранят свое значение перед присвоением.

Ответ №3:

Вот соответствующая документация. В частности,

Перед началом выполнения составного оператора, который формирует тело функции конструктора, завершается инициализация всех прямых баз, виртуальных баз и нестатических элементов данных. Список инициализаторов элементов — это место, где может быть указана инициализация этих объектов не по умолчанию. Для членов, которые не могут быть инициализированы по умолчанию, таких как члены ссылочных и константных типов, должны быть указаны инициализаторы членов.

Итак, если ваш пользовательский конструктор копирования в конечном итоге не копирует vector элемент, то ваша копия будет неверной, поскольку в vector конечном итоге будет сконструирован по умолчанию. Программа на C будет полностью корректной синтаксически — конструктор копирования просто не будет «правильным». Это относится в целом ко всем конструктивным элементам по умолчанию. Если у вас есть элемент, который не может быть сконструирован по умолчанию, код просто не будет компилироваться.