C++ 为什么将未使用的返回值强制转换为void?

C++ 为什么将未使用的返回值强制转换为void?,c++,c,void,C++,C,Void,是否有任何理由将未使用的返回值转换为void,或者我认为这完全是浪费时间 后续行动: 这似乎很全面。我认为这比注释未使用的返回值要好,因为自文档化代码比注释好。就我个人而言,我会关闭这些警告,因为这是不必要的噪音 如果一个bug因为它而逃逸,我会收回我的话…在工作中,我们用它来确认函数有一个返回值,但开发人员断言忽略它是安全的。既然你把问题标记为C++,你应该使用STATICE-CAST: static_cast(fn()); 就编译器而言,将返回值强制转换为void没有什么意义。强制转换为v

是否有任何理由将未使用的返回值转换为void,或者我认为这完全是浪费时间

后续行动:

这似乎很全面。我认为这比注释未使用的返回值要好,因为自文档化代码比注释好。就我个人而言,我会关闭这些警告,因为这是不必要的噪音


如果一个bug因为它而逃逸,我会收回我的话…

在工作中,我们用它来确认函数有一个返回值,但开发人员断言忽略它是安全的。既然你把问题标记为C++,你应该使用STATICE-CAST:

static_cast(fn());

就编译器而言,将返回值强制转换为void没有什么意义。

强制转换为void是无成本的。这只是编译器如何处理它的信息

David的文章几乎涵盖了这一点的动机,明确地向其他“开发人员”表明,您知道此函数返回,但您明确地忽略了它

这是一种确保始终处理必要错误代码的方法

我认为C++可能是我更喜欢使用C样式的样式表,因为使用完整的静态转换标记在这里感觉就像是过度的。最后,如果您正在审查编码标准或编写编码标准,那么明确声明对重载运算符的调用(不使用函数调用表示法)也应不受此限制也是一个好主意:

static_cast<void>(fn());

这样做的真正原因可以追溯到一个用于C代码的工具,名为


它分析代码,寻找可能的问题,并发出警告和建议。如果函数返回一个未被检查的值,
lint
将发出警告,以防这是意外情况。要使
lint
对该警告静音,您可以调用
(void)

,因为向void强制转换程序的功能没有意义。我还认为,正如David在回答中所建议的那样,您不应该使用它向正在阅读代码的人发出信号。如果你想表达你的意图,最好使用评论。添加这样的演员阵容只会让人觉得奇怪,并对可能的原因提出疑问。只是我的意见…

强制转换为
void
用于禁止编译器对未使用的变量和未保存的返回值或表达式发出警告

标准(2003年)在§5.2.9/4中规定

任何表达式都可以显式转换为“cv void”类型。表达式值为丢弃

所以你可以写:

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.

也可以

此外,当验证代码是否符合MISTA(或其他)标准时,自动工具(如LDRA)将不允许您调用具有返回类型的函数而不让它返回值,除非您显式地将返回值强制转换为(void)

因为c++17我们有
[[可能未使用]]
属性,可以使用该属性代替
void
cast

C++17
[[nodiscard]]

C++17使用一个属性标准化了“返回值忽略业务”

因此,我希望兼容的实现总是只在给出
nodiscard
时发出警告,而不要在其他情况下发出警告

例如:

main.cpp

//suppressing  expressions
(void)(unusedVar);
(void)(fn());
(void)(x &&y || z);
汇编:

[[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() {
      | 
我无法直接在
f()
调用中使用
maybe\u unused

(void)f();
[[maybe_unused]] int i = f();
给出:

[[maybe_unused]] f();
(无效)
铸造加工似乎不是强制性的,但在标准中是“鼓励的”:

从警告消息中还可以看出,警告的一个“解决方案”是添加
-Wno unused result

main.cpp: In function ‘int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
    6 |     [[maybe_unused]] f();
      |     ^~~~~~~~~~~~~~~~
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp
尽管我当然不建议像这样忽略全球警告

C++20还允许您向
nodiscard
添加原因,如
[[nodiscard(“原因”)]]
中所述,如下所述:

GCC
warn\u unused\u结果
attribute

在标准化
[[nodiscard]]
之前,对于C,在他们最终决定标准化属性之前,GCC实现了与
warn\u unused\u result
完全相同的功能:

main.cpp: In function ‘int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
    6 |     [[maybe_unused]] f();
      |     ^~~~~~~~~~~~~~~~
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp
其中:

int f() __attribute__ ((warn_unused_result));

int f() {
    return 1;
}

int main() {
    f();
}
应注意的是,由于ANSI C没有这方面的标准,ANSI C没有指定哪些C标准库函数具有该属性或不具有该属性,因此实现已自行决定哪些函数应标记为
warn\u unused\u result
,这就是为什么通常必须使用
(void)
强制转换来忽略对标准库函数的任何调用的返回,以完全避免任何实现中的警告


在GCC 9.2.1、Ubuntu19.10中测试。

它是否抑制了关于未使用返回值的警告?不,它没有@Mykola:使用GCC4,您可以附加一个属性,该属性表示返回值不应被忽略,这将触发警告。我使用g++,即使使用此类强制转换,它也会发出警告。您使用哪个警告选项-Wunused值不会在我的环境中触发警告在VC++中,它会抑制警告这是我唯一喜欢c风格强制转换的地方。在我的编码标准中,我也会在“a+a;”上加上(void)(当然,经过适当的删减:p)有些离题,但是为什么不使用返回值就这样做“a+a;”?这对我来说真的像是滥用副作用,混淆了代码的意图。这将返回分配给对象(对于所有行为良好的类,即!:))。另一个例子是:os It可能以这种方式启动,但大多数工具现在都有其他机制来抑制类似这样的警告。另外,不管这是为什么开始的,特别是在安全关键代码领域,这已经成为“记录”开发人员意图的常用方式。
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();
      |     ~^~