Стандарты программирования на С++. 101 правило и рекомендация
Шрифт:
• Трудно безопасно использовать классы с членами или базовыми классами
• Вы не можете надежно создавать глобальные либо статические объекты
• Вы
• Вы не можете использовать объекты
Функции освобождения ресурсов, включая специальным образом перегруженные операторы
Помимо деструкторов и функций освобождения ресурсов распространенные безопасные методики основаны на том, что операции обмена не генерируют исключений. В данном случае это связано не с использованием их в реализациях отката, а с их использованием в гарантированном принятии результатов работы. Например, вот идиоматическая реализация оператора
(см. также рекомендацию 56)
К счастью, область видимости сбоя при освобождении ресурса имеет определенно меньший размер. Если для сообщения об ошибке используются исключения, убедитесь, что рассматриваемые функции обрабатывают все возможные исключения и прочие ошибки, которые могут возникнуть при работе функций. (В случае исключений просто оберните все, что делает ваш деструктор, в блок
При использовании в качестве механизма обработки ошибок исключений следует документировать такое поведение, объявляя
такие функции с закомментированной пустой спецификацией исключений[C++03] §15.2(3), §17.4.4.8(3) • [Meyers96] §11 • [Stroustrup00] §14.4.7, §E.2-4 • [Sutter00] §8, §16 • [Sutter02] §18-19
52. Копируйте и ликвидируйте согласованно
Если вы определили одну из следующего списка функций — копирующий конструктор, оператор копирующего присваивания или деструктор — вероятно, вам потребуется определить и обе оставшиеся функции (или по крайней мере одну из них).
Если вам требуется определить одну из трех перечисленный функций, это означает, что вам требуется нечто большее, чем поведение этой функции по умолчанию, а все эти функции асимметрично взаимосвязаны.
• Если вы пишете или запрещаете копирующий конструктор или оператор копирующего присваивания, то, вероятно, вы должны сделать то же самое и для другой функции из этой пары. Если одна функция выполняет некоторую "специальную" работу, вероятно, другая должна делать что-то аналогичное, так как эти две функции должны иметь одинаковое действие (см. рекомендацию 53, которая поясняет этот пункт).
• Если вы явно пишете копирующие функции, вероятно, вам надо явно написать и деструктор. Если "специальная" работа в копирующем конструкторе заключается в выделении или дублировании некоторого ресурса (например, памяти, файла, сокета), то вы должны освободить этот ресурс в деструкторе.
• Если вы явно пишете деструктор, вероятно, вам требуется явно написать (или явно запретить) копирование. Если вам нужен нетривиальный деструктор, это зачастую связано с тем, что вам требуется вручную освободить ресурс, хранящийся объектом. Если так, вероятно, для этого ресурса требуется аккуратное дублирование, так что вам следует уделить внимание способу копирования и присваивания объектов, либо полностью запретить таковое.
Во многих случаях хранение корректно инкапсулированного ресурса с использованием идиомы RAII позволяет полностью избежать самостоятельной разработки указанных операций (см. рекомендацию 13).
Предпочитайте специальные члены, сгенерированные компилятором. Только они могут рассматриваться как "тривиальные", и как минимум один крупный производитель STL использует оптимизацию для классов с тривиальными специальными функциями. Похоже, вскоре это станет распространенным явлением.
Когда любая из специальных функций объявлена только для того, чтобы сделать ее закрытой или виртуальной, но без специальной семантики, это не приводит к необходимости наличия остальных функций.
В редких случаях классы, имеющие члены странных типов (например, ссылки,