[[nodiscard("reason")]]能让编译器在警告时输出自定义提示,Clang 12.0+和MSVC 2019 16.11+支持显示reason字符串,GCC目前忽略该内容,仅作诊断提示,不参与编译检查。

[[nodiscard("reason")]] 能让编译器在警告时输出自定义提示
普通 [[nodiscard]] 只会触发类似 “ignoring return value of function declared with ‘nodiscard’ attribute” 的通用警告,不说明为什么这个返回值不该被忽略。而 [[nodiscard("reason")]] 允许你嵌入一段字符串,在编译器生成诊断(warning 或 error)时直接显示它,帮助调用者快速理解设计意图。
不同编译器对 reason 字符串的支持程度不一
Clang 从 12.0 开始完整支持该字符串,并原样输出到警告信息中;GCC 目前(截至 13.x)虽接受语法,但会静默忽略 "reason" 内容,仅给出标准 nodiscard 提示;MSVC(VS 2019 16.11+)支持且会在 IntelliSense 和构建输出中显示该字符串。
- 实际效果取决于编译器,不能假设所有环境都可见
- 字符串内容不参与编译期检查,仅作提示用途
- 建议用简短、动词开头的短语,例如
"result must be checked for errors"或"caller must free the buffer"
典型使用场景:资源获取、错误敏感操作、状态变更函数
这类函数一旦忽略返回值,容易引发内存泄漏、逻辑跳过或未处理错误。加带 reason 的 nodiscard 是一种轻量但明确的契约强化方式。
[[nodiscard("must check if allocation succeeded")]]
void* allocate(size_t n);
[[nodiscard("error code indicates I/O failure")]]
int read_data(char* buf, size_t len);
// 调用时若写成 allocate(1024);,Clang 会报:
// warning: ignoring return value of function declared with 'nodiscard' attribute
// [-Wnodiscard]
// note: reason: must check if allocation succeeded
和返回值类型语义配合才能真正起效
单独加 [[nodiscard("...")]] 不会阻止编译,也不会改变行为——它只影响诊断质量。真正防止误用,还得靠类型设计:
立即学习“C++免费学习笔记(深入)”;
- 返回
std::expected或自定义 result 类型,比裸int更难被静默丢弃 - 避免为明显无副作用的 getter(如
size())滥用该属性,否则会干扰正常使用 - 如果函数本就应被忽略(比如 logging 函数),别加 nodiscard,哪怕带 reason
reason 字符串再清晰,也救不了语义模糊的接口设计。重点还是让返回值类型本身“说话”。











