}
(см. также рекомендацию 56)
К счастью, область видимости сбоя при освобождении ресурса имеет определенно меньший размер. Если для сообщения об ошибке используются исключения, убедитесь, что рассматриваемые функции обрабатывают все возможные исключения и прочие ошибки, которые могут возникнуть при работе функций. (В случае исключений просто оберните все, что делает ваш деструктор, в блок try/catch(...)
.) Это чрезвычайно важно, поскольку деструктор может быть вызван в кризисной ситуации, такой как сбой при выделении системного ресурса (например, памяти, файлов, блокировок, портов, окон или других системных объектов).
При использовании в качестве механизма обработки ошибок исключений следует документировать такое поведение, объявляя такие функции с закомментированной пустой спецификацией исключений /* throw() */
(см. рекомендацию 75).
52. Копируйте и ликвидируйте согласованно
Если вы определили одну из следующего списка функций — копирующий конструктор, оператор копирующего присваивания или деструктор — вероятно, вам потребуется определить и обе оставшиеся функции (или по крайней мере одну из них).
Если вам требуется определить одну из трех перечисленный функций, это означает, что вам требуется нечто большее, чем поведение этой функции по умолчанию, а все эти функции асимметрично взаимосвязаны.
•
•
•
Во многих случаях хранение корректно инкапсулированного ресурса с использованием идиомы RAII позволяет полностью избежать самостоятельной разработки указанных операций (см. рекомендацию 13).
Предпочитайте специальные члены, сгенерированные компилятором. Только они могут рассматриваться как "тривиальные", и как минимум один крупный производитель STL использует оптимизацию для классов с тривиальными специальными функциями. Похоже, вскоре это станет распространенным явлением.
Когда любая из специальных функций объявлена только для того, чтобы сделать ее закрытой или виртуальной, но без специальной семантики, это не приводит к необходимости наличия остальных функций.
В редких случаях классы, имеющие члены странных типов (например, ссылки, std::auto_ptr
), являются исключениями, поскольку они имеют необычную семантику копирования. В классе, хранящем ссылку или auto_ptr
, вам, вероятно, потребуется написать копирующий конструктор и оператор присваивания, но деструктор по умолчанию будет работать корректно. (Заметим, что использование члена, являющегося ссылкой или auto_ptr
, почти всегда ошибочно).
53. Явно разрешайте или запрещайте копирование
Копируйте со знанием дела: тщательно выбирайте между использованием сгенерированных компилятором копирующего конструктора и оператора присваивания, написанием собственных версий или явным запрещением обоих, если копирование не должно быть разрешено.