Страницы

Поиск по вопросам

вторник, 2 октября 2018 г.

Что такое атрибуты в C++?

Начиная со стандарта c++11 в языке появились так называемые "атрибуты", что это такое и зачем они нужны?


Ответ

Атрибуты позволяют задавать дополнительную информацию для различных конструкций языка, таких как типы, переменные, имена, блоки и единицы трансляции. Данная информация в частности может быть использована компилятором для генерации более эффективного кода и предоставления (или наоборот, подавления) предупреждающих сообщений пользователю на уровне конкретных участков кода, а не целой программы или компилируемого файла, как это обеспечивается ключами компиляции.
Атрибуты появились в c++11 и к текущему стандарту c++17 были несколько расширены. На данный момент существуют следующие стандартные атрибуты:
carries_dependency deprecated fallthrough maybe_unused nodiscard noreturn
Набор атрибутов может быть расширен каждой конкретной реализацией компилятора, в таком случае его поведение будет описываться отдельно. Неизвестный атрибут будет проигнорирован, но может быть выведено предупреждающее сообщение.
Атрибут всегда обрамляется двойными квадратными скобками:
[[атрибут]]

Пойдём по порядку:
[[carries_dependency]]
Данный атрибут не изменяет смысл программы, но может приводить к генерации более эффективного кода. Атрибут может применяться как к целой функции, так и к её параметрам. Может быть полезен на системах со слабо упорядоченной архитектурой при передаче значения между вычислительными потоками. Самый сложный для понимания атрибут :) Поэтому за дополнительной информацией - на enSO.
[[deprecated]]
Позволяет отметить сущность устаревшей или небезопасной, но тем не менее пока ещё разрешённой к использованию. Может применяться к объявлению класса, typedef-имени, переменной, нестатическому члену данных, функции, пространству имён, перечислению, элементу перечисления или специализации шаблона. Атрибут может быть снабжен аргументом, заданным строковым литералом. Например:
[[deprecated("используйте функцию g()")]] void f();
Текстовое сообщение будет использовано как подсказка при выводе соответствующего предупреждения.
[[fallthrough]]
Данный атрибут применяется к пустой операции, т.е. . Может быть использован только внутри switch для уведомления компилятора о задуманном программистом "проваливании" цепочки действий из одной ветки case в другую. Атрибут позволяет подавлять предупреждение компилятора, которое он может выдать, если между метками case не будет обнаружен оператор break. Часто отсутствие break может быть банальной ошибкой, возникшей по невнимательности. Пример:
switch (i) { case 1: ... [[fallthrough]]; case 2: ... }
[[maybe_unused]]
Используется для уведомления компилятора о том, что сущность может быть не использована в программе и следует подавлять соответствующее предупреждение. Может применяться к объявлению класса, typedef-имени, переменной, нестатическому члену данных, функции, пространству имён, перечислению или элементу перечисления. Атрибут может быть полезен при наличии отладочного кода, который не будет включён в бинарник при сборке в release режиме. Пример:
[[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); }
Ранее приходилось использовать приведение к void для подавления возможных предупреждений.
[[nodiscard]]
Указывает на обязательность использования результата при возврате из функции. Может быть применим как к типу (при объявлении класса или перечисления), так и непосредственно к возвращаемому типу функции. Пример:
[[nodiscard]] int f() { return 42; } ... f(); // сообщение о том, что результат функции не использован
Явное приведение результата к void подавляет действие атрибута:
static_cast(f()); // нет предупреждения о не использованном результате
[[noreturn]]
Говорит о том, что функция не возвращает управление. Может быть применим к объявлению функции. Актуально для функций, которые заканчивают свою работу выкидыванием исключения, выполняют вечный цикл или прерывают выполнение всей программы. Пример:
[[noreturn]] void f() { throw "error"; }
Если функция, помеченная атрибутом [[noreturn]], возвращает управление на одной из веток выполнения, то это приводит к неопределённому поведению.

Комментариев нет:

Отправить комментарий