- •Герб Саттер
 - •Как пользоваться этой книгой
 - •Стандарты кодирования и вы
 - •Об этой книге
 - •Благодарности
 - •Вопросы организации и стратегии
 - •0. Не мелочитесь, или Что не следует стандартизировать Резюме
 - •Обсуждение
 - •Примеры
 - •1. Компилируйте без замечаний при максимальном уровне предупреждений Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •2. Используйте автоматические системы сборки программ Резюме
 - •Обсуждение
 - •3. Используйте систему контроля версий Резюме
 - •Обсуждение
 - •Исключения
 - •Стиль проектирования
 - •5. Один объект — одна задача Резюме
 - •Обсуждение
 - •Примеры
 - •6. Главное — корректность, простота и ясность Резюме
 - •Обсуждение
 - •Примеры
 - •7. Кодирование с учетом масштабируемости Резюме
 - •Обсуждение
 - •8. Не оптимизируйте преждевременно Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •10. Минимизируйте глобальные и совместно используемые данные Резюме
 - •Обсуждение
 - •Исключения
 - •11. Сокрытие информации Резюме
 - •Обсуждение
 - •Исключения
 - •13. Ресурсы должны быть во владении объектов Резюме
 - •Обсуждение
 - •Исключения
 - •Стиль кодирования
 - •14. Предпочитайте ошибки компиляции и компоновки ошибкам времени выполнения Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •Примеры
 - •16. Избегайте макросов Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •17. Избегайте магических чисел Резюме
 - •Обсуждение
 - •Примеры
 - •18. Объявляйте переменные как можно локальнее Резюме
 - •Обсуждение
 - •Исключения
 - •Примеры
 - •Исключения
 - •Исключения
 - •22. Минимизируйте зависимости определений и избегайте циклических зависимостей Резюме
 - •Обсуждение
 - •Исключения
 - •Примеры
 - •24. Используйте только внутреннюю, но не внешнюю защиту директивы #include Резюме
 - •Обсуждение
 - •Исключения
 - •Функции и операторы
 - •25. Передача параметров по значению, (интеллектуальному) указателю или ссылке Резюме
 - •Обсуждение
 - •26. Сохраняйте естественную семантику перегруженных операторов Резюме
 - •Обсуждение
 - •Исключения
 - •27. Отдавайте предпочтение каноническим формам арифметических операторов и операторов присваивания Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •30. Избегайте перегрузки &&, || и , (запятой) Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •Проектирование классов и наследование
 - •32. Ясно представляйте, какой вид класса вы создаете Резюме
 - •Обсуждение
 - •33. Предпочитайте минимальные классы монолитным Резюме
 - •Обсуждение
 - •34. Предпочитайте композицию наследованию Резюме
 - •Обсуждение
 - •Исключения
 - •35. Избегайте наследования от классов, которые не спроектированы для этой цели Резюме
 - •Обсуждение
 - •36. Предпочитайте предоставление абстрактных интерфейсов Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •Исключения
 - •Примеры
 - •39. Виртуальные функции стоит делать неоткрытыми, а открытые — невиртуальными Резюме
 - •Обсуждение
 - •Исключения
 - •Примеры
 - •Исключения
 - •41. Делайте данные-члены закрытыми (кроме случая агрегатов в стиле структур с) Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •42. Не допускайте вмешательства во внутренние дела Резюме
 - •Обсуждение
 - •Исключения
 - •43. Разумно пользуйтесь идиомой Pimpl Резюме
 - •Обсуждение
 - •Исключения
 - •Примеры
 - •Исключения
 - •Конструкторы, деструкторы и копирование
 - •47. Определяйте и инициализируйте переменные-члены в одном порядке Резюме
 - •Обсуждение
 - •48. В конструкторах предпочитайте инициализацию присваиванию Резюме
 - •Обсуждение
 - •Исключения
 - •Примеры
 - •50. Делайте деструкторы базовых классов открытыми и виртуальными либо защищенными и невиртуальными Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •51. Деструкторы, функции освобождения ресурсов и обмена не ошибаются Резюме
 - •Обсуждение
 - •52. Копируйте и ликвидируйте согласованно Резюме
 - •Обсуждение
 - •Исключения
 - •53. Явно разрешайте или запрещайте копирование Резюме
 - •Обсуждение
 - •54. Избегайте срезки. Подумайте об использовании в базовом классе клонирования вместо копирования Резюме
 - •Обсуждение
 - •Исключения
 - •56. Обеспечьте бессбойную функцию обмена Резюме
 - •Обсуждение
 - •Исключения
 - •Пространства имен и модули
 - •57. Храните типы и их свободный интерфейс в одном пространстве имен Резюме
 - •Обсуждение
 - •Примеры
 - •58. Храните типы и функции в разных пространствах имен, если только они не предназначены для совместной работы Резюме
 - •Обсуждение
 - •59. Не используйте using для пространств имен в заголовочных файлах или перед директивой #include Резюме
 - •Обсуждение
 - •Исключения
 - •60. Избегайте выделения и освобождения памяти в разных модулях Резюме
 - •Обсуждение
 - •61. Не определяйте в заголовочном файле объекты со связыванием Резюме
 - •Обсуждение
 - •Исключения
 - •62. Не позволяйте исключениям пересекать границы модулей Резюме
 - •Обсуждение
 - •63. Используйте достаточно переносимые типы в интерфейсах модулей Резюме
 - •Обсуждение
 - •Примеры
 - •65. Выполняйте настройку явно и преднамеренно Резюме
 - •Обсуждение
 - •66. Не специализируйте шаблоны функций Резюме
 - •Обсуждение
 - •67. Пишите максимально обобщенный код Резюме
 - •Обсуждение
 - •Исключения
 - •Обработка ошибок и исключения
 - •68. Широко применяйте assert для документирования внутренних допущений и инвариантов Резюме
 - •Обсуждение
 - •Примеры
 - •69. Определите разумную стратегию обработки ошибок и строго ей следуйте Резюме
 - •Обсуждение
 - •70. Отличайте ошибки от ситуаций, не являющихся ошибками Резюме
 - •Обсуждение
 - •Примеры
 - •71. Проектируйте и пишите безопасный в отношении ошибок код Резюме
 - •Обсуждение
 - •Примеры
 - •72. Для уведомления об ошибках следует использовать исключения Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •73. Генерируйте исключения по значению, перехватывайте — по ссылке Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •Исключения
 - •Stl: контейнеры
 - •76. По умолчанию используйте vector. В противном случае выбирайте контейнер, соответствующий задаче Резюме
 - •Обсуждение
 - •Примеры
 - •77. Вместо массивов используйте vector и string Резюме
 - •Обсуждение
 - •78. Используйте vector (и string::c_str) для обмена данными с api на других языках Резюме
 - •Обсуждение
 - •79. Храните в контейнерах только значения или интеллектуальные указатели Резюме
 - •Обсуждение
 - •Примеры
 - •80. Предпочитайте push_back другим способам расширения последовательности Резюме
 - •Обсуждение
 - •Исключения
 - •81. Предпочитайте операции с диапазонами операциям с отдельными элементами Резюме
 - •Обсуждение
 - •Примеры
 - •82. Используйте подходящие идиомы для реального уменьшения емкости контейнера и удаления элементов Резюме
 - •Обсуждение
 - •Исключения
 - •Stl: алгоритмы
 - •83. Используйте отладочную реализацию stl Резюме
 - •Обсуждение
 - •Примеры
 - •84. Предпочитайте вызовы алгоритмов самостоятельно разрабатываемым циклам Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •85. Пользуйтесь правильным алгоритмом поиска Резюме
 - •Обсуждение
 - •86. Пользуйтесь правильным алгоритмом сортировки Резюме
 - •Обсуждение
 - •Примеры
 - •Исключения
 - •87. Делайте предикаты чистыми функциями Резюме
 - •Обсуждение
 - •Примеры
 - •88. В качестве аргументов алгоритмов и компараторов лучше использовать функциональные объекты, а не функции Резюме
 - •Обсуждение
 - •89. Корректно пишите функциональные объекты Резюме
 - •Обсуждение
 - •Безопасность типов
 - •90. Избегайте явного выбора типов — используйте полиморфизм Резюме
 - •Обсуждение
 - •Примеры
 - •91. Работайте с типами, а не с представлениями Резюме
 - •Обсуждение
 - •92. Избегайте reinterpret_cast Резюме
 - •Обсуждение
 - •Исключения
 - •93. Избегайте применения static_cast к указателям Резюме
 - •Обсуждение
 - •94. Избегайте преобразований, отменяющих const Резюме
 - •Обсуждение
 - •Исключения
 - •95. Не используйте преобразование типов в стиле с Резюме
 - •Обсуждение
 - •96. Не применяйте memcpy или memcmp к не-pod типам Резюме
 - •Обсуждение
 - •97. Не используйте объединения для преобразований Резюме
 - •Обсуждение
 - •Исключения
 - •99. Не используйте недействительные объекты и небезопасные функции Резюме
 - •Обсуждение
 - •100. Не рассматривайте массивы полиморфно Резюме
 - •Обсуждение
 - •Список литературы
 - •Резюме из резюме
 - •8. Не оптимизируйте преждевременно
 - •15. Активно используйте const
 - •23. Делайте заголовочные файлы самодостаточными
 - •36. Предпочитайте предоставление абстрактных интерфейсов
 - •61. Не определяйте в заголовочном файле объекты со связыванием
 - •62. Не позволяйте исключениям пересекать границы модулей
 - •63. Используйте достаточно переносимые типы в интерфейсах модулей
 - •70. Отличайте ошибки от ситуаций, не являющихся ошибками
 - •71. Проектируйте и пишите безопасный в отношении ошибок код
 - •72. Для уведомления об ошибках следует использовать исключения
 - •73. Генерируйте исключения по значению, перехватывайте — по ссылке
 - •85. Пользуйтесь правильным алгоритмом поиска
 - •86. Пользуйтесь правильным алгоритмом сортировки
 - •87. Делайте предикаты чистыми функциями
 - •88. В качестве аргументов алгоритмов и компараторов лучше использовать функциональные объекты, а не функции
 
Примеры
Пример 1. Размещение фигурных скобок. Нет никакой разницы в плане удобочитаемости следующих фрагментов:
void using k_and_r_style() {
// ...
}
void putting_each_brace_on_its_own_line()
{
// ...
}
void or_putting_each_brace_on_its_own_line_indented()
{
// ...
}
Все профессиональные программисты могут легко читать и писать в каждом из этих стилей без каких-либо сложностей. Но следует быть последовательным. Не размещайте скобки как придется или так, что их размещение будет скрывать вложенность областей видимости, и пытайтесь следовать стилю, принятому в том или ином файле. В данной книге размещение скобок призвано обеспечить максимальную удобочитаемость, при этом оставаясь в рамках,
Пример 2. Пробелы или табуляция. В некоторых командах использование табуляции запрещено (например, [BoostLRG]) на том основании, что размер табуляции варьируется от редактора к редактору, а это приводит к тому, что отступы оказываются слишком малы или слишком велики. В других командах табуляции разрешены. Важно только быть последовательным. Если вы позволяете использовать табуляцию, убедитесь, что такое решение не будет мешать ясности кода и его удобочитаемости, если члены команды будут сопровождать код друг друга (см. руководство 6). Если использование табуляции не разрешено, позвольте редактору преобразовывать пробелы в табуляции при чтении исходного файла, чтобы программисты могли работать с ними в редакторе. Однако убедитесь, что при сохранении файла
Пример 3. Венгерская запись. Запись, при которой информация о типе включается в имя переменной, приносит пользу в языке программирования, небезопасном с точки зрения типов (особенно в С); возможна, хотя и не приносит никакой пользы (только недостатки) в объектно-ориентированных языках; и невозможна в обобщенном программировании. Таким образом, стандарт кодирования С++ не должен требовать использования венгерской записи, более того, может требовать её запрета.
Пример 4. Один вход, один выход (Single entry, single exit — "SESE"). Исторически некоторые стандарты кодирования требуют, чтобы каждая функция имела в точности один выход, что подразумевает одну инструкцию return. Такое требование является устаревшим в языках, поддерживающих исключения и деструкторы, так что функции обычно имеют несколько неявных выходов. Вместо этого стоит следовать стандарту наподобие рекомендации 5, которая требует от функций простоты и краткости, что делает их более простыми для понимания
Ссылки
[BoostLRG] • [Brooks95] §12 • [Constantine95] §29 • [Keffer95] p. 1 • [Kernighan99] §1.1, §1.3, §1.6-7 • [Lakos96] §1.4.1, §2.7 • [McConnell93] §9, §19 • [Stroustrup94] §4.2-3 • [Stroustrup00] §4.9.3, §6.4, §7.8, §С.1 [Sutter00] §6.1, §20 [SuttHysl01]
1. Компилируйте без замечаний при максимальном уровне предупреждений Резюме
Следует серьезно относиться к предупреждениям компилятора и использовать максимальный уровень вывода предупреждений вашим компилятором. Компиляция должна выполняться без каких-либо предупреждений. Вы должны понимать все выдаваемые предупреждения и устранять их путем изменения кода, а не снижения уровня вывода предупреждений.
