Последнее обновление:2026-10-12
Атрибут [[nodiscard]] в C++17¶
С момента появления в C++17 атрибута [[nodiscard]] у нас есть более мощный инструмент для разработки API, позволяющий помечать возвращаемые значения функций, которые не должны игнорироваться при вызове. В этой статье мы подробно рассмотрим применение [[nodiscard]] и обратим внимание на некоторые потенциальные ловушки.
Что такое [[nodiscard]]?¶
[[nodiscard]] — это атрибут функции, который сообщает компилятору, что возвращаемое значение функции не должно игнорироваться. Это особенно полезно для функций, чья работа зависит от возвращаемого значения, например функций-предикатов или фабричных функций.
Как использовать [[nodiscard]]?¶
[[nodiscard]] можно применять к классам, конструкторам и перечислениям. Вот несколько примеров:
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] B() = default;
};
enum class [[nodiscard]] State {
Default,
Foo,
Bar
};
В приведённых примерах компилятор будет выдавать предупреждение, когда возвращаемое значение игнорируется, что помогает заранее обнаруживать потенциальные баги.
Осторожно: ловушки [[nodiscard]]¶
Хотя [[nodiscard]] эффективно предотвращает непреднамеренное игнорирование возвращаемых значений, следует помнить о некоторых потенциальных ловушках. Распространённая ловушка — функция с [[nodiscard]] возвращает объект, похожий на scope guard, чтобы выполнить очистку по завершении области видимости (например, зафиксировать транзакцию).
[[nodiscard]] ScopeGuard createScopeGuard() {
// Implementation of a scope guard
}
// 在这里,用户可以选择忽略返回值,导致作用域立即销毁,从而失去清理效果
std::ignore = createScopeGuard();
Несмотря на то что [[nodiscard]] указывает, что возвращаемое значение функции не должно игнорироваться, пользователь всё же может явно проигнорировать возвращаемое значение, например с помощью std::ignore, и тем самым обойти операцию очистки.
Полный пример¶
#include <tuple> // std::ignore
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] bool isOk() const { return true; }
};
// no need for nodiscard, A is nodiscard
A foo() {
return A();
}
// B is not nodiscard, mark it explicitly
[[nodiscard]] B bar() {
return B();
}
int main()
{
foo(); // warning: ignoring temporary created by a constructor declared with 'nodiscard' attribute
bar(); // warning
std::ignore = foo(); // ok
auto b = bar(); // ok
b.isOk(); // warning
if (b.isOk()) {} // ok
}
Похожие темы¶
- std::string_view в C++17 | C++那些事
- PMR-ресурсы памяти в C++17 | C++那些事
- Семнадцать расширенных возможностей C++17 | C++那些事
- Выведение аргументов шаблона класса CTAD в C++17 | C++那些事
- C++17 optional_ref | C++那些事
- std::variant в C++17 | C++那些事
- Структурированные привязки в C++17 | C++那些事
- Выведение auto в шаблонах C++17 | C++那些事
- Шаблоны переменных в C++17 | C++那些事