Умные указатели и конструкторы копирования
Насколько я понимаю, главная причина предоставления определяемого пользователем конструктора копирования заключается в том, что мы должны обеспечить глубокое копирование указателей на элементы данных.
Означает ли это, что если мы заменим необработанные члены-указатели на интеллектуальные указатели, частота предоставления пользовательских конструкторов копирования уменьшится?
3 ответа
Да, это так. Если вы используете только типы, которые знают, как семантически копировать ваши данные, вам не нужно перезаписывать конструктор копирования по умолчанию.
Теперь вопрос был изменен, ответ - да, если вы используете умный указатель, который выполняет глубокое копирование обернутого объекта, когда этот умный указатель копируется.
Ранее касалось только общего указателя: Нет, поскольку при копировании общего указателя получаются два общих указателя, которые указывают на один и тот же объект. Если у вас есть объект с общим указателем на подобъект и вы копируете его, и вы хотите, чтобы у нового объекта была своя собственная копия подобъекта (глубокая копия), вам нужно будет сделать это в конструкторе копирования или использовать другой вид умного указателя.
Правильный ответ - нет. Вам необходимо определить конструктор копирования для любого класса с членами-указателями (совместно используемыми или иными), если только значение указателя не является тем, которое необходимо скопировать. Исключение подразумевает, что содержимое памяти по адресу, хранящемуся в указателе, управляется другим классом.
Общий указатель поддерживает счетчик ссылок, чтобы управлять областью выделенной памяти, но он не управляет содержимым памяти и не копирует ссылочные данные. Таким образом, разделяемый указатель освобождает программиста от необходимости управлять областью объектов, размещенных в куче. Но это не освобождает программиста от необходимости определять конструктор копирования для объектов, которые содержат указатели на динамически размещаемые данные.
В этом контексте термин "умный указатель" является синонимом общего указателя. В частности, указанным интеллектуальным указателем является std::shared_ptr, который хранит счетчик ссылок, как описано. Лучший способ избежать написания конструкторов копирования - это следовать шаблону разработки, известному как Resource Acquisition Is Initialization (RAII). Этот тип шаблона проектирования хранит данные о членах, размещенные в стеке, так что деструкторы-члены вызываются автоматически при разматывании стека.
Концепция создания интеллектуальных указателей, которые выполняют неявные операции копирования, на самом деле не имеет смысла. Хотя можно разыменовать указатель для получения копируемых данных, для копирования требуется новый указатель. Вся идея использования указателей (или ссылок) состоит в том, чтобы получить доступ к общей области памяти и избежать копирования.