Gre*_*een 14 c++ compiler-warnings c++17 nodiscard c++-attributes
在使用 C++20 的项目中,CLion 建议我添加[[nodiscard]]到我的 const 类方法定义中,例如,
class Test {
public:
[[nodiscard]] int f(int a, int b) const {
return a + b;
}
}
Run Code Online (Sandbox Code Playgroud)
解释是
向成员函数添加 [[nodiscard]] 属性(在 C++17 中引入),以便在编译时突出显示哪些返回值不应被忽略。
我还检查了cppreference.com:
如果从废弃值表达式(而不是强制转换为 void)调用声明为 nodiscard 的函数或按值返回声明为 nodiscard 的枚举或类的函数,则鼓励编译器发出警告。... 出现在函数声明、枚举声明或类声明中。
如果从丢弃值表达式而不是强制转换为 void,
- 调用声明为 nodiscard 的函数,或者
- 调用返回按值声明为 nodiscard 的枚举或类的函数,或者
- 通过显式类型转换或 static_cast 调用声明为 nodiscard 的构造函数,或者
- 声明为 nodiscard 的枚举或类类型的对象通过显式类型转换或 static_cast 进行初始化,
鼓励编译器发出警告。
老实说,我不太明白为什么这个位置需要这个注释。如果调用者进一步处理它们,为什么编译器会忽略我的返回值?是否有一个直观的解释来解释它到底告诉编译器什么以及为什么需要它?
ypn*_*nos 20
这个想法是,如果只有当您还获取函数的返回值时调用函数才有意义,那么在不获取返回值的情况下调用它是一个编程错误。该注释[[nodiscard]]可以帮助与您的代码交互的程序员避免此错误。
在您的具体示例中,您的函数计算结果没有副作用,因此静态代码分析器意识到它非常适合[[nodiscard]]. 例如:
Test a;
auto x = a.f(1, 2); // ok
std::cout << "For 1, 2 we get " << a.f(1,2) << std::endl; // also ok
a.f(1, 2); // warning here
Run Code Online (Sandbox Code Playgroud)
这里鼓励编译器在最后一行警告函数调用,而不进一步处理结果。
一个很好用的例子[[discard]]是操作对象的对象方法,但以副本形式提供结果。例子:
DateTime yesterday = DateTime.now().substractOneDay();
std::cout << "Yesterday was " << yesterday.nameOfDay() << std::endl;
Run Code Online (Sandbox Code Playgroud)
对比:
DateTime yesterday = DateTime.now();
yesterday.substractOneDay();
std::cout << "Yesterday was " << yesterday.nameOfDay() << std::endl;
Run Code Online (Sandbox Code Playgroud)
A[[nodiscard]]会告诉第二个例子的程序员,他们使用的是错误的。
[[nodiscard]]当您有返回某些内容的类方法并且您想强调该方法不能就地工作而是返回某些内容时,这很有用。
例如,如果您有一个链接列表,reverse则可以标记一个可能的方法[[nodiscard]]以表明该方法返回一个新列表。
它有助于避免这样的代码:
List l{1, 2, 3, 4};
l.reverse();
std::cout << l;
>> 1, 2, 3, 4 //Why is this not working?
Run Code Online (Sandbox Code Playgroud)
对我来说,最有用的地方似乎[[nodiscard]]是当你有一个方法/函数可以修改对象/参数但也返回一些东西时(所以方法/函数不能是const)。
List l{1, 2, 3, 4};
l.doubleEveryElementAndSum(); //the sum returned is silently ignored
std::cout << l;
>> 2, 4, 6, 8
Run Code Online (Sandbox Code Playgroud)
CLion 会突出显示该方法并告诉您该方法可以被标记,这一事实[[nodiscard]与 CLion 或编译器无关,而是与 clang-tidy 工具有关。该工具会扫描您的代码并检查您可以改进的地方,然后 CLion 可视化该工具的结果。
当您编译代码时,编译器将读取注释,并在发现忽略标记的函数的返回值的代码时发出警告[[nodiscard]]。
我的建议是不要[[nodiscard]]像 CLion (clang-tidy) 建议的那样到处放置,从而污染您的代码。如果您觉得这些警告很烦人,您可以在 clang-tidy 设置中禁用它们。
| 归档时间: |
|
| 查看次数: |
9012 次 |
| 最近记录: |