Чтение онлайн

на главную - закладки

Жанры

Стандарты программирования на С++. 101 правило и рекомендация

Александреску Андрей

Шрифт:
Резюме

Если вы определили одну из следующего списка функций — копирующий конструктор, оператор копирующего присваивания или деструктор — вероятно, вам потребуется определить и обе оставшиеся функции (или по крайней мере одну из них).

Обсуждение

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

• Если вы пишете или запрещаете

копирующий конструктор или оператор копирующего присваивания, то, вероятно, вы должны сделать то же самое и для другой функции из этой пары. Если одна функция выполняет некоторую "специальную" работу, вероятно, другая должна делать что-то аналогичное, так как эти две функции должны иметь одинаковое действие (см. рекомендацию 53, которая поясняет этот пункт).

• Если вы явно пишете копирующие функции, вероятно, вам надо явно написать и деструктор. Если "специальная" работа в копирующем конструкторе заключается в выделении или дублировании некоторого ресурса (например, памяти, файла, сокета), то вы должны освободить этот ресурс в деструкторе.

• Если вы явно пишете деструктор, вероятно, вам требуется явно написать (или явно запретить) копирование. Если вам нужен нетривиальный деструктор, это зачастую связано с тем, что вам требуется вручную освободить ресурс, хранящийся объектом. Если так, вероятно, для этого ресурса требуется аккуратное дублирование, так что вам следует уделить внимание способу копирования и присваивания объектов, либо полностью запретить таковое.

Во многих случаях хранение корректно инкапсулированного ресурса с использованием идиомы RAII позволяет полностью избежать самостоятельной разработки указанных операций (см. рекомендацию 13).

Предпочитайте специальные члены, сгенерированные компилятором. Только они могут рассматриваться как "тривиальные", и как минимум один крупный производитель STL использует оптимизацию для классов с тривиальными специальными функциями. Похоже, вскоре это станет распространенным явлением.

Исключения

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

В редких случаях классы, имеющие члены странных типов (например, ссылки,

std::auto_ptr
), являются исключениями, поскольку они имеют необычную семантику копирования. В классе, хранящем ссылку или
auto_ptr
, вам, вероятно, потребуется написать копирующий конструктор и оператор присваивания, но деструктор по умолчанию будет работать корректно. (Заметим, что использование члена, являющегося ссылкой или
auto_ptr
, почти всегда ошибочно).

Ссылки

[Cline99] §30.01-14 • [Koenig97] §4 • [Stroustrup00] §5.5, §10.4 • [SuttHysl04b]

53. Явно разрешайте или запрещайте копирование

Резюме

Копируйте

со знанием дела: тщательно выбирайте между использованием сгенерированных компилятором копирующего конструктора и оператора присваивания, написанием собственных версий или явным запрещением обоих, если копирование не должно быть разрешено.

Обсуждение

Распространенной ошибкой (и не только среди новичков) является игнорирование семантики копирования и присваивания при определении класса. Это характерно для маленьких вспомогательных классов, таких как предназначенные для поддержки идиомы RAII (см. рекомендацию 13).

Убедитесь, что ваш класс предоставляет осмысленное копирование (или не предоставляет его вовсе). Вот возможные варианты.

• Явное запрещение обеих функций. Если копирование для вашего типа лишено смысла, запретите как копирующее конструирование, так и копирующее присваивание, объявив их как закрытые нереализованные функции:

class T { // ...

private: // Делаем T некопируемым

 T(const T&); // Функция не реализована

 T& operator=(const T&); // Функция не реализована

};

• Явное написание обеих функций. Если для объектов

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

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

Заметим, что запрещение копирования и копирующего присваивания означает, что вы не можете поместить объекты

T
в стандартные контейнеры. Это не обязательно плохо; очень может быть, что вы в любом случае не захотите хранить такие объекты в контейнерах. (Тем не менее, вы все равно можете поместить эти объекты в контейнер, если будете хранить их посредством интеллектуальных указателей; см. рекомендацию 79).

Вывод: будьте внимательны при работе с этими двумя операциями, так как компилятор имеет тенденцию к самостоятельной их генерации, а эти сгенерированные версии зачастую небезопасны для типов, не являющихся значениями (см. также рекомендацию 32).

Ссылки

[Dewhurst03] §88 • [Meyers97] §11 • [Stroustrup00] §11.2.2

54. Избегайте срезки. Подумайте об использовании в базовом классе клонирования вместо копирования

Поделиться:
Популярные книги

Долгий путь домой

Русич Антон
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
6.20
рейтинг книги
Долгий путь домой

Убивать чтобы жить 6

Бор Жорж
6. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 6

Возвышение Меркурия. Книга 3

Кронос Александр
3. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 3

Фиктивная жена

Шагаева Наталья
1. Братья Вертинские
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Фиктивная жена

Здравствуй, 1985-й

Иванов Дмитрий
2. Девяностые
Фантастика:
альтернативная история
5.25
рейтинг книги
Здравствуй, 1985-й

Барон Дубов 4

Карелин Сергей Витальевич
4. Его Дубейшество
Фантастика:
юмористическое фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Барон Дубов 4

Лекарь для захватчика

Романова Елена
Фантастика:
попаданцы
историческое фэнтези
фэнтези
5.00
рейтинг книги
Лекарь для захватчика

Идеальный мир для Лекаря 24

Сапфир Олег
24. Лекарь
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Идеальный мир для Лекаря 24

Ваше Сиятельство 9

Моури Эрли
9. Ваше Сиятельство
Фантастика:
боевая фантастика
попаданцы
стимпанк
аниме
фэнтези
5.00
рейтинг книги
Ваше Сиятельство 9

Господин следователь

Шалашов Евгений Васильевич
1. Господин следователь
Детективы:
исторические детективы
5.00
рейтинг книги
Господин следователь

Академия проклятий. Книги 1 - 7

Звездная Елена
Академия Проклятий
Фантастика:
фэнтези
8.98
рейтинг книги
Академия проклятий. Книги 1 - 7

Полковник Гуров. Компиляция (сборник)

Макеев Алексей Викторович
Полковник Гуров
Детективы:
криминальные детективы
шпионские детективы
полицейские детективы
боевики
крутой детектив
5.00
рейтинг книги
Полковник Гуров. Компиляция (сборник)

Первый среди равных. Книга V

Бор Жорж
5. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга V

Землянка для двух нагов

Софи Ирен
Фантастика:
космическая фантастика
5.00
рейтинг книги
Землянка для двух нагов