13.2. Управление копированием и ресурсами
Обычно классы, управляющие ресурсами, расположенными вне его, должны определять функции-члены управления копированием. Как упоминалось в разделе 13.6, такие классы нуждаются в деструкторах, освобождающих зарезервированные объектом ресурсы. Если класс нуждается в деструкторе, он почти наверняка нуждается также в конструкторе копий и операторе присвоения копии.
Чтобы определить эти функции-члены, сначала следует решить, что будет означать копирование объекта данного типа. Вообще, есть два способа: операцию копирования можно определить так, чтобы класс вел себя, как значение или как указатель.
У классов, которые ведут себя, как значения, есть собственное состояние. При копировании объекта как значения копия и оригинал независимы друг от друга. Внесенные в копию изменения никак не влияют на оригинал, и наоборот.
Классы, действующие как указатели, используют состояние совместно. При копировании объектов таких классов копии и оригиналы используют те же данные. Изменения, внесенные в копии, изменяют также оригинал, и наоборот.
Из использованных ранее библиотечных классов поведением, подобным значениям, обладали классы библиотечных контейнеров и класс string. Ничего удивительного, что класс shared_ptr демонстрирует поведение, подобное указателю, как и класс StrBlob (см. раздел 12.1.1). Типы ввода-вывода и класс unique_ptr не допускают ни копирования, ни присвоения, поэтому их поведение не похоже ни на значение, ни на указатель.
Чтобы проиллюстрировать эти два подхода, определим для используемого в упражнениях класса HasPtr функции-члены управления копированием. Сначала заставим класс действовать, как значение, а затем повторно реализуем его в версии, ведущей себя, как указатель.
У класса HasPtr есть два члена типа int и указатель на тип string. Обычно классы непосредственно копируют переменные-члены встроенного типа (кроме указателей); такие члены являются значениями, а следовательно, ведут себя обычно, как значения. Происходящее при копировании указателя-члена определяет то, должно ли у такого класса, как HasPtr, быть поведение, подобное значению или указателю.
Упражнения раздела 13.2
Упражнение 13.22. Предположим, класс HasPtr должен вести себя, как значение. Таким образом, у каждого его объекта должна быть собственная копия строки, на которую указывает объект. Определения функций-членов управления копированием рассматривается в следующем разделе, но уже сейчас известно все необходимое для их реализации. Напишите конструктор копий класса HasPtr и оператор присвоения копии прежде, чем продолжите чтение.