int fn();
void whatever()
{
(void) fn();
}
是否有任何理由将未使用的返回值转换为 void,还是我认为这完全是浪费时间?
跟进:
嗯,这似乎很全面。我认为这比注释未使用的返回值要好,因为自记录代码比注释更好。就个人而言,我会关闭这些警告,因为它是不必要的噪音。
如果有虫子因此逃跑,我会吃掉我的话......
大卫的回答几乎涵盖了这样做的动机,明确地向其他“开发人员”展示你知道这个函数返回但你明确地忽略它。
这是一种确保始终处理必要的错误代码的方法。
我认为对于 C++,这可能也是我更喜欢使用 C 风格转换的唯一地方,因为在这里使用完整的静态转换表示法感觉有点矫枉过正。最后,如果您正在审查编码标准或编写一个编码标准,那么明确声明对重载运算符的调用(不使用函数调用表示法)也应该免除此限制也是一个好主意:
class A {};
A operator+(A const &, A const &);
int main () {
A a;
a + a; // Not a problem
(void)operator+(a,a); // Using function call notation - so add the cast.
在工作中,我们使用它来确认函数具有返回值,但开发人员已断言忽略它是安全的。由于您将问题标记为 C++,因此您应该使用static_cast:
static_cast<void>(fn());
就编译器而言,将返回值强制转换为 void 没有什么意义。
这样做的真正原因可以追溯到用于 C 代码的工具,称为lint。
它分析代码以寻找可能的问题并发出警告和建议。如果函数返回了一个未检查的值,lint
则会发出警告以防意外。lint
要对此警告保持沉默,请将呼叫发送到(void)
。
转换void
为用于抑制未使用的变量和未保存的返回值或表达式的编译器警告。
标准(2003)在 §5.2.9/4 中说,
任何表达式都可以显式转换为类型“cv void”。表达式值被丢弃。
所以你可以写:
//suppressing unused variable warnings
static_cast<void>(unusedVar);
static_cast<const void>(unusedVar);
static_cast<volatile void>(unusedVar);
//suppressing return value warnings
static_cast<void>(fn());
static_cast<const void>(fn());
static_cast<volatile void>(fn());
//suppressing unsaved expressions
static_cast<void>(a + b * 10);
static_cast<const void>( x &&y || z);
static_cast<volatile void>( m | n + fn());
所有表格均有效。我通常将其缩短为:
//suppressing expressions
(void)(unusedVar);
(void)(fn());
(void)(x &&y || z);
它也可以。
从 c++17 开始,我们有了[[maybe_unused]]
可以用来代替强制转换的属性void
。
铸成无效是无成本的。它只是编译器如何处理它的信息。
对于您将程序转换为 void 的功能是没有意义的。我还认为你不应该使用它来向正在阅读代码的人发出信号,正如大卫在回答中所建议的那样。如果您想就您的意图传达一些信息,最好使用评论。添加这样的演员只会看起来很奇怪,并会引发有关可能原因的问题。只是我的观点...
此外,在验证您的代码是否符合 MISTA(或其他)标准时,LDRA 等自动工具将不允许您调用具有返回类型的函数而不返回值,除非您将返回值显式转换为 (void)
C++17[[nodiscard]]
C++17 用一个属性标准化了“返回值忽略业务”。
因此,我希望兼容的实现总是只在给出时才nodiscard
发出警告,否则永远不会发出警告。
例子:
主文件
[[nodiscard]] int f() {
return 1;
}
int main() {
f();
}
编译:
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -o main.out main.cpp
结果:
main.cpp: In function ‘int main()’:
main.cpp:6:6: warning: ignoring return value of ‘int f()’, declared with attribute nodiscard [-Wunused-result]
6 | f();
| ~^~
main.cpp:1:19: note: declared here
1 | [[nodiscard]] int f() {
|
以下都避免了警告:
(void)f();
[[maybe_unused]] int i = f();
我无法maybe_unused
直接在f()
通话中使用:
[[maybe_unused]] f();
给出:
main.cpp: In function ‘int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
6 | [[maybe_unused]] f();
| ^~~~~~~~~~~~~~~~
(void)
演员工作似乎不是强制性的,但在标准中是“鼓励的”:我怎样才能故意丢弃 [[nodiscard]] 返回值?
同样从警告消息中可以看出,警告的一个“解决方案”是添加-Wno-unused-result
:
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp
尽管我当然不建议像这样在全球范围内忽略警告。
C ++ 20 还允许您添加一个原因,nodiscard
如[[nodiscard("reason")]]
所述:https ://en.cppreference.com/w/cpp/language/attributes/nodiscard
GCCwarn_unused_result
属性
在 标准化之前[[nodiscard]]
,对于 C 在他们最终决定标准化属性之前,GCC 实现了与 完全相同的功能warn_unused_result
:
int f() __attribute__ ((warn_unused_result));
int f() {
return 1;
}
int main() {
f();
}
这使:
main.cpp: In function ‘int main()’:
main.cpp:8:6: warning: ignoring return value of ‘int f()’, declared with attribute warn_unused_result [-Wunused-result]
8 | f();
| ~^~
应该注意的是,由于 ANSI C 对此没有标准,因此 ANSI C 没有指定哪些 C 标准库函数具有该属性,因此实现已经自己决定应该用 标记或不标记什么warn_unuesd_result
。这就是为什么通常您必须使用(void)
强制转换来忽略对标准库函数的任何调用的返回,以完全避免任何实现中的警告。
在 GCC 9.2.1、Ubuntu 19.10 中测试。