IT_Abyss
IT_Abyss
Главная
База знаний
СТЕКИ
C++
Go
Python
C#
Java
JavaScript
TypeScript
QA / Тестирование
PHP
Kotlin / Android
Swift / iOS
Аналитика данных
Машинное обучение
Безопасность
DevOps / SRE
Системный анализ
Unreal Engine
C++
BACKEND · ENGINE
Roadmap
Граф зависимостей по темам
→
Best practices
Идиомы и анти-паттерны
→
Questions
Вопросы к собеседованиям
→
Собеседование
Блог
Тарифы
Поиск по сайту
Поиск
Ctrl K
Отзыв
Войти
Telegram
cpp
/
guidelines
C++
▾
Loading
.
.
.
Меню · раздел
База знаний
Roadmap
Граф зависимостей по темам
Questions
Вопросы к собеседованиям
Roadmap
Выбери направление
C++
Go
Python
C#
Java
JavaScript
TypeScript
QA / Тестирование
PHP
Kotlin / Android
Swift / iOS
Аналитика данных
Машинное обучение
Безопасность
DevOps / SRE
Системный анализ
Unreal Engine
Questions
Выбери направление
C++
Go
Python
C#
Java
JavaScript
TypeScript
QA / Тестирование
PHP
Kotlin / Android
Swift / iOS
Аналитика данных
Машинное обучение
Безопасность
DevOps / SRE
Системный анализ
Unreal Engine
Меню
Главная
База знаний
Собеседование
Блог
Аккаунт
C++
C++ Core Guidelines
Официальное руководство по написанию современного C++
In
Introduction
1 правило
▼
P
Philosophy
13 правил
▼
I
Interfaces
20 правил
▼
F
Functions
40 правил
▼
C
Classes and class hierarchies
100 правил
▼
Enum
Enumerations
8 правил
▼
R
Resource management
25 правил
▼
ES
Expressions and statements
66 правил
▼
Per
Performance
18 правил
▼
CP
Concurrency and parallelism
33 правила
▼
E
Error handling
22 правила
▼
Con
Constants and immutability
5 правил
▼
T
Templates and generic programming
54 правила
▼
CPL
C-style programming
3 правила
▼
SF
Source files
16 правил
▼
SL
The Standard Library
4 правила
▼
A
Architectural ideas
3 правила
▼
NR
Non-Rules and myths
7 правил
▼
NL
Naming and layout suggestions
20 правил
▼
FAQ
Answers to frequently asked questions
21 правило
▼
Все правила C++ Core Guidelines
In.0: Не паникуйте!
P.1: Выражайте идеи непосредственно в коде
P.2: Пишите на стандартном ISO C++
P.3: Выражайте намерение
P.4: В идеале программа должна быть статически типобезопасной
P.5: Предпочитайте проверку во время компиляции проверке во время выполнения
P.6: То, что нельзя проверить во время компиляции, должно быть проверяемым во время выполнения
P.7: Обнаруживайте ошибки времени выполнения как можно раньше
P.8: Не допускайте утечек ресурсов
P.9: Не тратьте впустую время и память
P.10: Предпочитайте неизменяемые данные изменяемым
P.11: Инкапсулируйте запутанные конструкции, а не разбрасывайте их по коду
P.12: Используйте вспомогательные инструменты там, где это уместно
P.13: Используйте вспомогательные библиотеки там, где это уместно
I.1: Делайте интерфейсы явными
I.2: Избегайте не-const глобальных переменных
I.3: Избегайте синглтонов
I.4: Делайте интерфейсы точно и строго типизированными
I.5: Указывайте предусловия (если они есть)
I.6: Предпочитайте Expects() для выражения предусловий
I.7: Указывайте постусловия
I.8: Предпочитайте Ensures() для выражения постусловий
I.9: Если интерфейс является шаблоном, документируйте его параметры с помощью концептов
I.10: Используйте исключения для сигнализации о невозможности выполнить требуемую задачу
I.11: Никогда не передавайте владение через сырой указатель (T*) или ссылку (T&)
I.12: Объявляйте указатель, который не должен быть null, как not_null
I.13: Не передавайте массив как единственный указатель
I.22: Избегайте сложной инициализации глобальных объектов
I.23: Сохраняйте небольшое количество аргументов функции
I.24: Избегайте соседних параметров, которые могут быть вызваны с теми же аргументами в любом порядке с разным смыслом
I.25: Предпочитайте пустые абстрактные классы в качестве интерфейсов иерархиям классов
I.26: Если вам нужен межкомпиляторный ABI, используйте подмножество в стиле C
I.27: Для стабильного ABI библиотеки рассмотрите идиому Pimpl
I.30: Инкапсулируйте нарушения правил
F.1: «Упаковывайте» значимые операции в тщательно именованные функции
F.2: Функция должна выполнять единственную логическую операцию
F.3: Держите функции короткими и простыми
F.4: Если функция может потребоваться для вычисления во время компиляции, объявите её constexpr
F.5: Если функция очень мала и критична по времени, объявите её inline
F.6: Если ваша функция не должна бросать, объявите её noexcept
F.7: Для общего использования принимайте аргументы T* или T&, а не умные указатели
F.8: Предпочитайте чистые функции
F.9: Неиспользуемые параметры должны быть безымянными
F.10: Если операция может быть повторно использована, дайте ей имя
F.11: Используйте безымянную лямбду, если нужен простой функциональный объект только в одном месте
F.15: Предпочитайте простые и общепринятые способы передачи информации
F.16: Для «входных» параметров передавайте дешёво копируемые типы по значению, остальные — по ссылке на const
F.17: Для параметров «вход-выход» передавайте по ссылке на не-const
F.18: Для параметров «будет перемещено из» передавайте через X&& и используйте std::move для параметра
F.19: Для «прямых» параметров передавайте через TP&& и только std::forward параметр
F.20: Для «выходных» значений предпочитайте возвращаемые значения выходным параметрам
F.21: Для возврата нескольких «выходных» значений предпочитайте возврат структуры
F.60: Предпочитайте T* вместо T&, когда «нет аргумента» является допустимым вариантом
F.22: Используйте T* или owner<T*> для обозначения одиночного объекта
F.23: Используйте not_null<T> для обозначения того, что null является недопустимым значением
F.24: Используйте span<T> или span_p<T> для обозначения полуоткрытой последовательности
F.25: Используйте zstring или not_null<zstring> для обозначения строки в стиле C
F.26: Используйте unique_ptr<T> для передачи владения там, где нужен указатель
F.27: Используйте shared_ptr<T> для разделения владения
F.42: Возвращайте T* для обозначения позиции (только)
F.43: Никогда (прямо или косвенно) не возвращайте указатель или ссылку на локальный объект
F.44: Возвращайте T&, когда копирование нежелательно и «вернуть ничего» не требуется
F.45: Не возвращайте T&&
F.46: int является типом возвращаемого значения для main()
F.47: Возвращайте T& из операторов присваивания
F.48: Не пишите return std::move(local)
F.49: Не возвращайте const T
F.50: Используйте лямбду, когда функция не подходит (для захвата локальных переменных или написания локальной функции)
F.51: Там, где есть выбор, предпочитайте аргументы по умолчанию перегрузке
F.52: Предпочитайте захват по ссылке в лямбдах, которые используются локально, включая передаваемые алгоритмам
F.53: Избегайте захвата по ссылке в лямбдах, которые используются нелокально, включая возвращаемые, хранящиеся в куче или передаваемые другому потоку
F.54: При написании лямбды, захватывающей this или любой член данных класса, не используйте захват по умолчанию [=]
F.55: Не используйте аргументы va_arg
F.56: Избегайте излишней вложенности условий
C.1: Организуйте связанные данные в структуры (struct или class)
C.2: Используйте class, если класс имеет инвариант; используйте struct, если члены данных могут изменяться независимо
C.3: Представляйте различие между интерфейсом и реализацией с помощью класса
C.4: Делайте функцию членом только если ей нужен прямой доступ к представлению класса
C.5: Размещайте вспомогательные функции в том же пространстве имён, что и поддерживаемый ими класс
C.7: Не определяйте класс или перечисление и не объявляйте переменную этого типа в одном операторе
C.8: Используйте class, а не struct, если какой-либо член не является публичным
C.9: Минимизируйте открытость членов
C.10: Предпочитайте конкретные типы иерархиям классов
C.11: Делайте конкретные типы регулярными
C.12: Не делайте члены данных const или ссылками в копируемом или перемещаемом типе
C.13: Если член данных B использует другой член данных A, объявляйте A перед B
C.20: Если можно избежать определения операций по умолчанию — избегайте
C.21: Если вы определяете или =delete какую-либо функцию копирования, перемещения или деструктора — определите или =delete их все
C.22: Делайте операции по умолчанию согласованными
C.30: Определяйте деструктор, если классу требуется явное действие при уничтожении объекта
C.31: Все ресурсы, захваченные классом, должны быть освобождены деструктором класса
C.32: Если класс имеет сырой указатель (T*) или ссылку (T&), рассмотрите, может ли он быть владельцем
C.33: Если класс имеет владеющий указатель-член, определите деструктор
C.35: Деструктор базового класса должен быть либо публичным и виртуальным, либо защищённым и невиртуальным
C.36: Деструктор не должен завершаться с ошибкой
C.37: Делайте деструкторы noexcept
C.40: Определите конструктор, если класс имеет инвариант
C.41: Конструктор должен создавать полностью инициализированный объект
C.42: Если конструктор не может построить корректный объект, выбросьте исключение
C.43: Убедитесь, что копируемый класс имеет конструктор по умолчанию
C.44: Предпочитайте конструкторам по умолчанию быть простыми и не выбрасывающими
C.45: Не определяйте конструктор по умолчанию, который только инициализирует члены данных; вместо этого используйте инициализаторы членов по умолчанию
C.46: По умолчанию объявляйте конструкторы с одним аргументом явными
C.47: Определяйте и инициализируйте члены данных в порядке их объявления
C.48: Предпочитайте инициализаторы членов по умолчанию инициализаторам членов в конструкторах для постоянных инициализаторов
C.49: Предпочитайте инициализацию назначению в конструкторах
C.50: Используйте фабрику, если вам нужно "виртуальное поведение" во время инициализации
C.51: Используйте делегирующие конструкторы для представления общих действий для всех конструкторов класса
C.52: Используйте наследование конструкторов для импорта конструкторов в производный класс, который не нуждается в дополнительной явной инициализации
C.60: Сделайте копирующее присваивание не-virtual, принимайте параметр const& и возвращайте не-const&
C.61: Операция копирования должна копировать
C.62: Сделайте присваивание копии безопасным для самоприсваивания
C.63: Сделайте присваивание перемещения не-virtual, примите параметр по && и вернитесь по не-const&
C.64: Операция перемещения должна перемещать и оставлять свой источник в допустимом состоянии
C.65: Сделайте переместительное присваивание безопасным для самоприсваивания
C.66: Сделайте операции перемещения noexcept
C.67: Полиморфный класс должен подавлять открытое копирование/перемещение
C.80: Используйте =default если вы должны явно указать использование семантики по умолчанию
C.81: Используйте =delete когда вы хотите отключить поведение по умолчанию (без желания предоставить альтернативу)
C.82: Не вызывайте виртуальные функции в конструкторах и деструкторах
C.83: Для типов, похожих на значения, рассмотрите возможность предоставления функции noexcept swap
C.84: Функция swap не должна давать сбой
C.85: C.85: Сделайте swap() свободной функцией и другом вашего класса
C.86: Сделайте == симметричным относительно типов операндов и noexcept
C.87: Остерегайтесь == на базовых классах
C.89: Сделайте hash noexcept
C.90: Полагайтесь на конструкторы и операторы присваивания, а не на memset и memcpy
C.100: Следуйте STL при определении контейнера
C.101: Дайте контейнеру семантику значения
C.102: Дайте контейнеру операции перемещения
C.103: C.103: Не пишите оператор присваивания, который может выбросить исключение
C.104: C.104: Используйте функцию-фабрику для конструирования объектов
C.109: Если дескриптор ресурса имеет семантику указателя, предоставьте * и ->
C.120: Используйте иерархии классов для представления концепций с присущей иерархической структурой (только)
C.121: Если базовый класс используется в качестве интерфейса, сделайте его чистым абстрактным классом
C.122: Используйте абстрактные классы как интерфейсы, когда требуется полное разделение интерфейса и реализации
C.126: Абстрактный класс обычно не требует написанного пользователем конструктора
C.127: Класс с виртуальной функцией должен иметь виртуальный или защищённый деструктор
C.128: Виртуальные функции должны указывать ровно один из virtual, override или final
C.129: При проектировании иерархии классов различайте наследование реализации и наследование интерфейса
C.130: Для глубокого копирования полиморфных классов предпочитайте виртуальную функцию clone вместо открытого копирования/присваивания конструктора
C.131: Избегайте тривиальных геттеров и сеттеров
C.132: Не делайте функцию virtual без причины
C.133: C.133: Избегайте protected данных
C.134: Убедитесь, что все не-const члены данных имеют одинаковый уровень доступа
C.135: Используйте множественное наследование для представления нескольких различных интерфейсов
C.136: Используйте множественное наследование для представления объединения атрибутов реализации
C.137: Используйте virtual-базы для избежания слишком общих базовых классов
C.138: Создавайте набор перегрузок для производного класса и его баз с помощью using
C.139: Используйте final для классов умеренно
C.140: Не предоставляйте разные аргументы по умолчанию для виртуальной функции и переопределяющей функции
C.145: Обращайтесь к полиморфным объектам через указатели и ссылки
C.146: Используйте dynamic_cast там, где навигация по иерархии классов неизбежна
C.147: Используйте dynamic_cast к ссылочному типу, когда отсутствие требуемого класса считается ошибкой
C.148: Используйте dynamic_cast к типу указателя, когда отсутствие требуемого класса считается допустимой альтернативой
C.149: Используйте unique_ptr или shared_ptr, чтобы не забыть вызвать delete для объектов, созданных с помощью new
C.150: Используйте make_unique() для создания объектов, которыми владеют unique_ptr
C.151: Используйте make_shared() для создания объектов, которыми владеют shared_ptr
C.152: Никогда не присваивайте указатель на массив объектов производного класса указателю на его базу
C.153: Предпочитайте виртуальную функцию приведению
C.160: Определяйте операторы прежде всего для имитации традиционного использования
C.161: Используйте нечленовые функции для симметричных операторов
C.162: Перегружайте операции, которые примерно эквивалентны
C.163: Перегружайте только операции, которые примерно эквивалентны
C.164: Избегайте операторов неявного преобразования
C.165: Используйте using для точек настройки
C.166: Перегружайте унарный & только как часть системы умных указателей и ссылок
C.167: Используйте оператор для операции с его традиционным значением
C.168: Определяйте перегруженные операторы в пространстве имён их операндов
C.170: Если хочется перегрузить лямбду — используйте обобщённую лямбду
C.180: Используйте union для экономии памяти
C.181: Избегайте «голых» union
C.182: Используйте анонимные union для реализации тегированных объединений
C.183: Не используйте union для каламбура типов
Enum.1: Предпочитайте перечисления макросам
Enum.2: Используйте перечисления для представления наборов связанных именованных констант
Enum.3: Предпочитайте enum class «обычным» enum
Enum.4: Определяйте операции над перечислениями для безопасного и удобного использования
Enum.5: Не используйте ALL_CAPS для значений перечислений
Enum.6: Избегайте безымянных перечислений
Enum.7: Указывайте базовый тип перечисления только при необходимости
Enum.8: Указывайте значения элементов перечисления только при необходимости
R.1: Управляйте ресурсами автоматически, используя дескрипторы ресурсов и RAII
R.2: В интерфейсах используйте сырые указатели только для обозначения отдельных объектов
R.3: Сырой указатель (T*) не владеет объектом
R.4: Сырая ссылка (T&) не владеет объектом
R.5: Предпочитайте объекты с ограниченным временем жизни; без необходимости не выделяйте память в куче
R.6: Избегайте неконстантных глобальных переменных
R.10: Избегайте malloc() и free()
R.11: Избегайте явных вызовов new и delete
R.12: Немедленно передавайте результат явного выделения ресурса объекту-менеджеру
R.13: Выполняйте не более одного явного выделения ресурса в одном выражении-операторе
R.14: Избегайте параметров-массивов [], предпочитайте span
R.15: Всегда перегружайте согласованные пары выделения/освобождения памяти
R.20: Используйте unique_ptr или shared_ptr для выражения владения
R.21: Предпочитайте unique_ptr вместо shared_ptr, если не нужно разделять владение
R.22: Используйте make_shared() для создания shared_ptr
R.23: Используйте make_unique() для создания unique_ptr
R.24: Используйте std::weak_ptr для разрыва циклов shared_ptr
R.30: Принимайте умные указатели в качестве параметров только для явного выражения семантики времени жизни
R.31: Если у вас есть умные указатели не из std, следуйте базовому паттерну из std
R.32: Принимайте параметр unique_ptr<widget> для выражения того, что функция принимает владение widget
R.33: Принимайте параметр unique_ptr<widget>& для выражения того, что функция переустанавливает widget
R.34: Принимайте параметр shared_ptr<widget> для выражения разделённого владения
R.35: Принимайте параметр shared_ptr<widget>& для выражения того, что функция может переустановить общий указатель
R.36: Принимайте параметр const shared_ptr<widget>&, чтобы выразить, что он может сохранить счётчик ссылок на объект
R.37: Не передавайте указатель или ссылку, полученные из псевдонима умного указателя
ES.1: Предпочитайте стандартную библиотеку другим библиотекам и «ручному коду»
ES.2: Предпочитайте подходящие абстракции прямому использованию возможностей языка
ES.3: Не повторяйтесь, избегайте избыточного кода
ES.5: Держите области видимости небольшими
ES.6: Объявляйте имена в инициализаторах и условиях оператора for для ограничения области видимости
ES.7: Держите общие и локальные имена короткими, а редкие и нелокальные — длиннее
ES.8: Избегайте похожих по написанию имён
ES.9: Избегайте имён в стиле ALL_CAPS
ES.10: Объявляйте только одно имя на объявление
ES.11: Используйте auto для исключения излишнего повторения имён типов
ES.12: Не переиспользуйте имена во вложенных областях видимости
ES.20: Всегда инициализируйте объект
ES.21: Не вводите переменную (или константу) до того, как она вам понадобится
ES.22: Не объявляйте переменную, пока не получите значение для её инициализации
ES.23: Предпочитайте синтаксис инициализации {}
ES.24: Используйте unique_ptr<T> для хранения указателей
ES.25: Объявляйте объект const или constexpr, если не планируете изменять его значение в дальнейшем
ES.26: Не используйте переменную для двух не связанных между собой целей
ES.27: Используйте std::array или stack_array для массивов на стеке
ES.28: Используйте лямбды для сложной инициализации, особенно переменных const
ES.30: Не используйте макросы для манипуляций с текстом программы
ES.31: Не используйте макросы для констант и «функций»
ES.32: Используйте ALL_CAPS для всех имён макросов
ES.33: If you must use macros, give them unique names
ES.34: Don't define a (C-style) variadic function
ES.40: Избегайте сложных выражений
ES.41: При сомнениях в приоритете операторов используйте скобки
ES.42: Держите использование указателей простым и понятным
ES.43: Избегайте выражений с неопределённым порядком вычислений
ES.44: Не зависьте от порядка вычисления аргументов функции
ES.45: Избегайте «магических констант»; используйте символические константы
ES.46: Избегайте сужающих (потерь, усечений) арифметических преобразований
ES.47: Используйте nullptr вместо 0 или NULL
ES.48: Избегайте приведений типов
ES.49: Если необходимо использовать приведение типа, используйте именованное приведение
ES.50: Не снимайте const приведением типа
ES.55: Избегайте необходимости проверки границ диапазона
ES.56: Используйте std::move() только тогда, когда нужно явно переместить объект в другую область видимости
ES.60: Избегайте new и delete за пределами функций управления ресурсами
ES.61: Удаляйте массивы через delete[], а не-массивы через delete
ES.62: Не сравнивайте указатели в разных массивах
ES.63: Не допускайте срезки объектов
ES.64: Используйте нотацию T{e} для конструирования объектов
ES.65: Не разыменовывайте недействительный указатель
ES.70: Предпочитайте оператор switch оператору if, когда есть выбор
ES.71: Предпочитайте range-for обычному for, когда есть выбор
ES.72: Предпочитайте for оператору while, когда есть очевидная переменная цикла
ES.73: Предпочитайте while оператору for, когда нет очевидной переменной цикла
ES.74: Предпочитайте объявлять переменную цикла в части инициализации оператора for
ES.75: Избегайте оператора do
ES.76: Избегайте goto
ES.77: Минимизируйте использование break и continue в циклах
ES.78: Не полагайтесь на неявный проваливание в операторах switch
ES.79: Используйте default только для обработки общих случаев
ES.84: Не пытайтесь объявить локальную переменную без имени
ES.85: Делайте пустые операторы видимыми
ES.86: Не изменяйте переменные управления циклом внутри тела сырых for-циклов
ES.87: Не добавляйте избыточные == или != в условия
ES.100: Не смешивайте знаковую и беззнаковую арифметику
ES.101: Используйте беззнаковые типы для битовых операций
ES.102: Используйте знаковые типы для арифметики
ES.103: Не допускайте переполнения
ES.104: Не допускайте нижнего переполнения (underflow)
ES.105: Не делите целое на ноль
ES.106: Не пытайтесь избежать отрицательных значений с помощью unsigned
ES.107: Не используйте unsigned для индексов, предпочитайте gsl::index
Per.1: Не оптимизируйте без причины
Per.2: Не оптимизируйте преждевременно
Per.3: Не оптимизируйте то, что не является критичным для производительности
Per.4: Не считайте, что сложный код обязательно быстрее простого
Per.5: Не считайте, что низкоуровневый код обязательно быстрее высокоуровневого
Per.6: Не делайте заявлений о производительности без измерений
Per.7: Проектируйте с учётом возможности оптимизации
Per.10: Опирайтесь на статическую систему типов
Per.11: Переносите вычисления из времени выполнения во время компиляции
Per.12: Устраняйте избыточные псевдонимы
Per.13: Устраняйте избыточные косвенные обращения
Per.14: Минимизируйте количество выделений и освобождений памяти
Per.15: Не выделяйте память на критическом пути выполнения
Per.16: Используйте компактные структуры данных
Per.17: Объявляйте наиболее часто используемый член критичной по времени структуры первым
Per.18: Память — это время
Per.19: Предсказуемо обращаться к памяти
Per.30: Избегайте переключений контекста на критическом пути
CP.1: Предположите, что ваш код будет запущен как часть многопоточной программы
CP.2: Избегайте состояний гонки
CP.3: Минимизируйте явное совместное использование изменяемых данных
CP.4: Думайте в терминах задач, а не потоков
CP.8: Не пытайтесь использовать volatile для синхронизации
CP.9: По возможности используйте инструменты для проверки вашего конкурентного кода
CP.20: Используйте RAII, никогда простых lock()/unlock()
CP.21: Используйте std::lock() или std::scoped_lock для захвата нескольких mutexов
CP.22: Никогда не вызывайте неизвестный код при удержании блокировки (например, обратный вызов)
CP.23: Думайте об объединяющем thread как о контейнере с областью действия
CP.24: Думайте о thread как о глобальном контейнере
CP.25: Предпочитайте gsl::joining_thread вместо std::thread
CP.26: Не detach() поток
CP.31: Передавайте небольшое количество данных между потоками по значению, а не по ссылке или указателю
CP.32: Для совместного владения между несвязанными threads используйте shared_ptr
CP.40: Минимизируйте переключение контекста
CP.41: Минимизируйте создание и уничтожение потоков
CP.42: Не wait без условия
CP.43: Минимизируйте время, проведенное в критической секции
CP.44: Помните, что нужно назвать ваши lock_guards и unique_locks
CP.50: Определите mutex вместе с данными, которые он охраняет. Используйте synchronized_value<T>, где это возможно
CP.51: Не используйте захватывающие лямбда-выражения, которые являются корутинами
CP.52: Не держите блокировки или другие примитивы синхронизации через точки приостановки
CP.53: Параметры корутин не должны передаваться по ссылке
CP.60: Используйте future для возврата значения из одновременной задачи
CP.61: Используйте async() для порождения конкурентных задач
CP.100: Не используйте программирование без блокировок, если у вас нет абсолютной необходимости
CP.101: Не доверяйте комбинации вашего оборудования/компилятора
CP.102: Тщательно изучите литературу
CP.110: Не пишите собственное двойное проверенное блокирование для инициализации
CP.111: Используйте обычный паттерн, если вам действительно нужна двойная проверка блокировки
CP.200: Используйте volatile только для взаимодействия с памятью, не являющейся C++
CP.201: Сигналы
E.1: Разработайте стратегию обработки ошибок на ранних этапах проектирования
E.2: Выбросьте исключение, чтобы сигнализировать о том, что функция не может выполнить своё задание
E.3: Используйте исключения только для обработки ошибок
E.4: Разработайте стратегию обработки ошибок на основе инвариантов
E.5: Позвольте конструктору установить инвариант и выбросить, если он не может
E.6: Используйте RAII для предотвращения утечек
E.7: Укажите ваши предусловия
E.8: Укажите ваши постусловия
E.12: Используйте noexcept, когда выход из функции из-за throw невозможен или неприемлем
E.13: Никогда не выбрасывайте исключение, являясь прямым владельцем объекта
E.14: Используйте специально разработанные определённые пользователем типы как исключения (не встроенные типы)
E.15: Выбрасывайте по значению, ловите исключения из иерархии по ссылке
E.16: Деструкторы, распределение памяти, swap и копирование/перемещение типа исключения никогда не должны завершаться с ошибкой
E.17: Не пытайтесь перехватить каждое исключение в каждой функции
E.18: Минимизируйте явное использование try/catch
E.19: Используйте объект final_action для очистки, если подходящий дескриптор ресурса недоступен
E.25: Если нельзя бросать исключения, симулируйте RAII для управления ресурсами
E.26: Если нельзя бросать исключения, рассмотрите быстрый сбой
E.27: Если нельзя бросать исключения, используйте коды ошибок систематически
E.28: Избегайте обработки ошибок на основе глобального состояния (например, errno)
E.30: Не используйте спецификации исключений
E.31: Правильно упорядочивайте catch-блоки
Con.1: По умолчанию делайте объекты неизменяемыми
Con.2: По умолчанию делайте функции-члены const
Con.3: По умолчанию передавайте указатели и ссылки на const
Con.4: Используйте const для объектов, значения которых не изменяются после конструирования
Con.5: Используйте constexpr для значений, вычисляемых во время компиляции
T.1: Используйте шаблоны для повышения уровня абстракции кода
T.2: Используйте шаблоны для выражения алгоритмов, применимых ко многим типам аргументов
T.3: Используйте шаблоны для выражения контейнеров и диапазонов
T.4: Используйте шаблоны для манипуляции синтаксическими деревьями
T.5: Комбинируйте обобщённые и ОО-техники, усиливая их достоинства, но не их недостатки
T.10: Задавайте концепты для всех аргументов шаблона
T.11: Везде, где возможно, используйте стандартные концепты
T.12: Предпочитайте имена концептов вместо auto для локальных переменных
T.13: Предпочитайте сокращённую запись для простых концептов с одним типовым аргументом
T.20: Избегайте «концептов» без содержательной семантики
T.21: Требуйте полный набор операций для концепта
T.22: Задавайте аксиомы для концептов
T.23: Различайте уточнённый концепт и его более общий случай, добавляя новые паттерны использования
T.24: Используйте классы-теги или трейты для различения концептов, отличающихся только семантикой
T.25: Избегайте взаимодополняющих ограничений
T.26: Предпочитайте определять концепты через паттерны использования, а не через простой синтаксис
T.40: Используйте функциональные объекты для передачи операций алгоритмам
T.41: Требуйте в концептах шаблона только существенные свойства
T.42: Используйте псевдонимы шаблонов для упрощения записи и скрытия деталей реализации
T.43: Предпочитайте using вместо typedef для определения псевдонимов
T.44: Используйте шаблоны функций для вывода аргументов шаблона класса (где применимо)
T.46: (удалено)
T.47: Избегайте хорошо видимых неограниченных шаблонов с распространёнными именами
T.48: Если компилятор не поддерживает концепты, эмулируйте их через enable_if
T.49: По возможности избегайте стирания типов
T.60: Минимизируйте зависимости шаблона от контекста
T.61: Не перепараметризуйте члены (SCARY)
T.62: Размещайте члены шаблона класса, не зависящие от параметров шаблона, в нешаблонном базовом классе
T.64: Используйте специализацию для предоставления альтернативных реализаций шаблонов классов
T.65: Используйте диспетчеризацию по тегам для предоставления альтернативных реализаций функций
T.67: Используйте специализацию для предоставления альтернативных реализаций нестандартных типов
T.68: Используйте {} вместо () внутри шаблонов во избежание неоднозначностей
T.69: Внутри шаблона не вызывайте неквалифицированные не-члены-функции, если вы не намерены сделать их точками настройки
T.80: Не шаблонизируйте иерархию классов без необходимости
T.81: Не смешивайте иерархии и массивы
T.82: Линеаризуйте иерархию, когда виртуальные функции нежелательны
T.83: Не объявляйте шаблон функции-члена виртуальным
T.84: Используйте нешаблонную основную реализацию для обеспечения ABI-стабильного интерфейса
T.100: Используйте вариадические шаблоны, когда нужна функция с переменным числом аргументов разных типов
T.101: Как передавать аргументы вариадическому шаблону
T.102: Как обрабатывать аргументы вариадического шаблона
T.103: Не используйте вариативные шаблоны для однородных списков аргументов
T.120: Используйте метапрограммирование шаблонов только тогда, когда это действительно необходимо
T.121: Используйте метапрограммирование шаблонов главным образом для эмуляции концептов
T.122: Используйте шаблоны (обычно псевдонимы шаблонов) для вычисления типов во время компиляции
T.123: Используйте constexpr-функции для вычисления значений во время компиляции
T.124: Предпочитайте средства TMP из стандартной библиотеки
T.125: Если вам нужно выйти за рамки средств TMP стандартной библиотеки, используйте существующую библиотеку
T.140: Если операцию можно использовать повторно, дайте ей имя
T.141: Use an unnamed lambda if you need a simple function object in one place only
T.142: Use template variables to simplify notation
T.143: Не пишите непреднамеренно негенерический код
T.144: Не специализируйте шаблоны функций
T.150: Проверяйте соответствие класса концепту с помощью static_assert
CPL.1: Предпочитайте C++ языку C
CPL.2: Если вы вынуждены использовать C, применяйте общее подмножество C и C++ и компилируйте код C как C++
CPL.3: Если вы должны использовать C для интерфейсов, используйте C++ в коде вызова таких интерфейсов
SF.1: Используйте суффикс .cpp для файлов с кодом и .h для файлов с интерфейсами, если ваш проект уже не следует другому соглашению
SF.2: Заголовочный файл не должен содержать определения объектов или определения невстраиваемых функций
SF.3: Используйте заголовочные файлы для всех объявлений, применяемых в нескольких исходных файлах
SF.4: Включайте заголовочные файлы перед другими объявлениями в файле
SF.5: Файл .cpp должен включать заголовочный файл (файлы), определяющий его интерфейс
SF.6: Используйте директивы using namespace для переходного периода, для фундаментальных библиотек (таких как std) или внутри локальной области видимости (только)
SF.7: Не пишите using namespace в глобальной области видимости в заголовочном файле
SF.8: Используйте защиту от повторного включения (#include guards) для всех заголовочных файлов
SF.9: Избегайте циклических зависимостей между исходными файлами
SF.10: Избегайте зависимостей от неявно включённых имён
SF.11: Заголовочные файлы должны быть самодостаточными
SF.12: Предпочитайте форму с кавычками в #include для файлов, расположенных относительно включающего файла, и форму с угловыми скобками везде остальде
SF.13: Используйте переносимые идентификаторы заголовков в директивах #include
SF.20: Используйте namespace для выражения логической структуры
SF.21: Не используйте безымянное (анонимное) пространство имён в заголовочном файле
SF.22: Используйте безымянное (анонимное) пространство имён для всех внутренних/неэкспортируемых сущностей
SL.1: Используйте библиотеки везде, где это возможно
SL.2: Предпочитайте стандартную библиотеку другим библиотекам
SL.3: Не добавляйте нестандартные сущности в пространство имён std
SL.4: Используйте стандартную библиотеку типобезопасным способом
A.1: Отделяйте стабильный код от менее стабильного
A.2: Оформляйте потенциально переиспользуемые части в виде библиотеки
A.4: Не должно быть циклов между библиотеками
NR.1: Не настаивайте на том, чтобы все объявления находились в начале функции
NR.2: Не настаивайте на наличии только одного оператора return в функции
NR.3: Не избегайте исключений
NR.4: Не настаивайте на помещении каждого определения класса в отдельный исходный файл
NR.5: Не используйте двухфазную инициализацию
NR.6: Не помещайте все действия по очистке в конец функции и не используйте goto exit
NR.7: Не делайте члены данных protected
NL.1: Не пишите в комментариях то, что можно ясно выразить в коде
NL.2: Указывайте намерение в комментариях
NL.3: Делайте комментарии краткими
NL.4: Поддерживайте единый стиль отступов
NL.5: Избегайте кодирования информации о типе в названиях
NL.7: Сделайте длину имени примерно пропорциональной длине его области видимости
NL.8: Используйте единый стиль именования
NL.9: Используйте ALL_CAPS только для имён макросов
NL.10: Предпочитайте имена в стиле underscore_style
NL.11: Делайте литералы читаемыми
NL.15: Используйте пробелы экономно
NL.16: Используйте стандартный порядок объявления членов класса
NL.17: Используйте форматирование в стиле K&R
NL.18: Используйте формат объявления в стиле C++
NL.19: Избегайте имён, которые легко неправильно прочитать
NL.20: Не помещайте два оператора в одну строку
NL.21: Объявляйте только одно имя в одном объявлении
NL.25: Не используйте void в качестве типа аргумента
NL.26: Используйте стандартную нотацию const
NL.27: Используйте суффикс .cpp для файлов кода и .h для файлов интерфейсов
FAQ.1: Какую цель преследуют эти руководящие принципы?
FAQ.2: Когда и где была впервые анонсирована эта работа?
FAQ.3: Кто является авторами и сопровождающими этих руководящих принципов?
FAQ.4: Как я могу участвовать?
FAQ.5: Как стать редактором/сопровождающим?
FAQ.6: Одобрены ли эти руководящие принципы комитетом по стандартам ISO C++? Являются ли они стандартом?
FAQ.7: Если эти руководящие принципы не одобрены комитетом, почему они размещены на github.com/isocpp?
FAQ.8: Будет ли версия этих Руководящих принципов для C++98? Для C++11?
FAQ.9: Предлагают ли эти руководящие принципы новые возможности языка?
FAQ.10: Какой вариант Markdown используется в этих руководящих принципах?
FAQ.50: Что такое GSL (библиотека поддержки руководящих принципов)?
FAQ.51: Является ли [github.com/Microsoft/GSL](https://github.com/Microsoft/GSL) реализацией GSL?
FAQ.52: Почему в руководящие принципы не включена реальная реализация GSL?
FAQ.53: Почему типы GSL не были предложены через Boost?
FAQ.54: Одобрена ли GSL (библиотека поддержки руководящих принципов) комитетом по стандарту ISO C++?
FAQ.55: Если вы используете стандартные типы там, где они доступны, почему span<char> из GSL отличается от string_view из технической спецификации Library Fundamentals 1 и рабочего документа C++17? Почему бы не использовать одобренный комитетом string_view?
FAQ.56: Является ли owner тем же, что и предложенный observer_ptr?
FAQ.57: Является ли stack_array тем же, что и стандартный array?
FAQ.58: Является ли dyn_array тем же, что и vector или предложенный dynarray?
FAQ.59: Является ли Expects тем же, что и assert?
FAQ.60: Является ли Ensures тем же самым, что и assert?