конструктор копии С++ с членами shared_ptr

От cplusplus.com:

Редко вы столкнетесь с классом, который не содержит исходных указателей, но конструктор копии по умолчанию недостаточно. Пример этого - когда у вас есть объект с подсчетом ссылок. boost :: shared_ptr <> является примером.

Может ли кто-то уточнить это? Если у нас есть класс, содержащий boost::shared_ptr, не будет ли он создан, когда будет создан экземпляр класса, и, следовательно, конструктор shared_ptr не подойдет и не увеличит счетчик ссылок? Следующий код, например, копирует Inner правильно - почему бы не работать для shared_ptr?:

#include <iostream>
using namespace std;

class Inner
{
public:
 Inner() { cout << "inner default constructed" << endl;}
 Inner(const Inner& other) { cout << "inner properly copied" << endl;}
};

class Outer
{
 Inner i;
};

int main() { Outer o; Outer p(o); return 0;}

Ответ 1

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

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

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

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

Абзац плохо сформулирован, но я уверен, что речь идет о глубокой копии, но говорят, что shared_ptr не предоставит эту глубокую копию. Это верно, потому что это не то, для чего оно предназначено.

Ответ 2

Может ли кто-то уточнить это?

На самом деле, нет; это тарабарщина.

Если у нас есть класс, содержащий boost::shared_ptr, не будет ли он создан, когда будет создан экземпляр класса, и, следовательно, конструктор shared_ptr не подойдет и не увеличит счетчик ссылок?

Это так. shared_ptr правильно разработан с допустимой семантикой копирования, поэтому нет необходимости разбираться с ним специально при копировании объекта класса, содержащего один.

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

Ответ 3

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

Например, если вы копируете собаку, а собака имеет кость, то новая собака получает свою собственную кость, или она разделяет исходную кость?