Última atualização:2026-10-12
Atributo [[nodiscard]] no C++17¶
Desde que o C++17 introduziu o atributo [[nodiscard]], temos à disposição, ao escrever APIs, uma ferramenta mais poderosa para marcar valores de retorno de funções que não devem ser ignorados na chamada. Neste artigo, exploraremos em profundidade o uso de [[nodiscard]] e atentaremos para algumas armadilhas potenciais.
O que é [[nodiscard]]?¶
[[nodiscard]] é um atributo de função que informa ao compilador que o valor de retorno da função não deve ser ignorado. Ele é particularmente útil em funções que dependem do valor de retorno, como funções predicado ou funções fábrica.
Como usar [[nodiscard]]?¶
É possível usar [[nodiscard]] em classes, construtores e enumerações. Seguem alguns exemplos:
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] B() = default;
};
enum class [[nodiscard]] State {
Default,
Foo,
Bar
};
Nos exemplos acima, o compilador emitirá um aviso quando o valor de retorno for ignorado, o que nos ajuda a detectar bugs potenciais mais cedo.
Atenção: as armadilhas do [[nodiscard]]¶
Embora [[nodiscard]] possa impedir de forma eficaz que valores de retorno sejam ignorados involuntariamente, é preciso ficar atento a algumas armadilhas potenciais. Uma armadilha comum é uma função marcada com [[nodiscard]] retornar um objeto semelhante a um scope guard (guarda de escopo), para executar uma limpeza no fim do escopo (por exemplo, confirmar uma transação).
[[nodiscard]] ScopeGuard createScopeGuard() {
// Implementation of a scope guard
}
// 在这里,用户可以选择忽略返回值,导致作用域立即销毁,从而失去清理效果
std::ignore = createScopeGuard();
Embora [[nodiscard]] indique que o valor de retorno da função não deve ser ignorado, o usuário ainda pode ignorar explicitamente o valor de retorno por meios como std::ignore, burlando assim a operação de limpeza.
Exemplo completo¶
#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
}
Tópicos relacionados¶
- C++17 std::string_view | C++那些事
- Recursos de memória PMR no C++17 | C++那些事
- Dezessete funcionalidades avançadas do C++17 | C++那些事
- Dedução de argumentos de template de classe CTAD no C++17 | C++那些事
- C++17 optional_ref | C++那些事
- C++17 std::variant | C++那些事
- Vinculações estruturadas no C++17 | C++那些事
- Dedução com auto em templates no C++17 | C++那些事
- Templates de variável no C++17 | C++那些事