为什么将未使用的返回值转换为 void?
int fn();
void whatever()
{
(void) fn();
}
是否有任何理由将未使用的返回值强制转换为 void,或者我认为这完全是浪费时间?
int fn();
void whatever()
{
(void) fn();
}
Is there any reason for casting an unused return value to void, or am I right in thinking it's a complete waste of time?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
大卫的答案几乎涵盖了这样做的动机,明确地向其他“开发人员”表明您知道此函数返回但您明确忽略它。
这是一种确保始终处理必要的错误代码的方法。
我认为对于 C++,这可能是我也更喜欢使用 C 风格强制转换的唯一地方,因为在这里使用完整的静态强制转换表示法感觉有点矫枉过正。 最后,如果您正在审查或编写编码标准,那么明确声明对重载运算符(不使用函数调用表示法)的调用也应该免除这一点也是一个好主意:
David's answer pretty much covers the motivation for this, to explicitly show other "developers" that you know this function returns but you're explicitly ignoring it.
This is a way to ensure that where necessary error codes are always handled.
I think for C++ this is probably the only place that I prefer to use C-style casts too, since using the full static cast notation just feels like overkill here. Finally, if you're reviewing a coding standard or writing one, then it's also a good idea to explicitly state that calls to overloaded operators (not using function call notation) should be exempt from this too:
在工作中,我们用它来确认该函数有返回值,但开发人员断言忽略它是安全的。 由于您将问题标记为 C++,因此您应该使用static_cast:
就编译器而言,将返回值强制转换为 void 没有什么意义。
At work we use that to acknowledge that the function has a return value but the developer has asserted that it is safe to ignore it. Since you tagged the question as C++ you should be using static_cast:
As far as the compiler goes casting the return value to void has little meaning.
这样做的真正原因可以追溯到 C 代码上使用的工具,称为 lint。
它分析代码寻找可能的问题并发出警告和建议。 如果函数返回的值随后未被检查,
lint
会发出警告,以防这是意外情况。 要消除此警告的lint
,请将调用强制转换为(void)
。The true reason for doing this dates back to a tool used on C code, called lint.
It analyzes code looking for possible problems and issuing warnings and suggestions. If a function returned a value which was then not checked,
lint
would warn in case this was accidental. To silencelint
on this warning, you cast the call to(void)
.转换为
void
用于抑制编译器对未使用的变量和未保存的返回值或表达式发出警告。标准(2003)在§5.2.9/4 中说,
所以你可以写:
所有形式都是有效的。 我通常将其缩短为:
也可以。
Casting to
void
is used to suppress compiler warnings for unused variables and unsaved return values or expressions.The Standard(2003) says in §5.2.9/4 says,
So you can write :
All forms are valid. I usually make it shorter as:
Its also okay.
C++17 或更高版本
C++11 或更高版本
更新:不建议使用此方法,因为它可能会在规范的未来版本中出现问题。请参阅这篇文章进行更多讨论。
从 C++11 开始,您还可以这样做:
这应该在标有
[[nodiscard]]
的函数上实现相同的结果C++17 or greater
C++11 or greater
Update: this approach is not recommended as it could potentially break in future version of the spec. See this post for more discussion.
As of C++11 you can also do:
This should achieve the same result on functions marked with
[[nodiscard]]
从 c++17 开始,我们有了
[[maybe_unused]]
属性,可以使用它来代替void
强制转换。Since c++17 we have the
[[maybe_unused]]
attribute which can be used instead of thevoid
cast.施放至虚空是无成本的。 它只是编译器如何处理它的信息。
Cast to void is costless. It is only information for compiler how to treat it.
对于你的程序功能来说,强制转换为 void 是没有意义的。 我还认为,正如大卫的回答所建议的那样,您不应该使用它来向正在阅读代码的人发出某些信号。 如果您想传达您的意图,最好使用评论。 添加这样的演员表只会看起来很奇怪,并会引发对其可能原因的疑问。 只是我的观点...
For the functionality of you program casting to void is meaningless. I would also argue that you should not use it to signal something to the person that is reading the code, as suggested in the answer by David. If you want to communicate something about your intentions, it is better to use a comment. Adding a cast like this will only look strange and raise questions about the possible reason. Just my opinion...
C++17
[[nodiscard]]
C++17用一个属性标准化了“返回值忽略的业务”。
因此,我希望兼容的实现始终仅在给出 nodiscard 时发出警告,否则永远不会发出警告。
示例:
main.cpp
编译:
结果:
以下所有内容都避免了警告:
我无法直接在
f()
调用上使用maybe_unused
: 给出:
< code>(void) 强制转换工作似乎不是强制性的,但在标准中是“鼓励”的:如何故意丢弃 [[nodiscard]] 返回值?
另外从警告消息中可以看出,警告的一个“解决方案”是添加
-Wno-unused-result
:尽管我当然不会建议像这样全局忽略警告。
C++20 还允许您向
nodiscard
添加原因,如[[nodiscard("reason")]]
中所述,如:https://en.cppreference.com/w/cpp/language/attributes/nodiscard< strong>GCC
warn_unused_result
attribute在
[[nodiscard]]
标准化之前,对于 C 最终决定标准化属性之前,GCC 实现了完全相同的功能与warn_unused_result
:给出:
应该注意的是,由于 ANSI C 没有这方面的标准,ANSI C 没有指定哪些 C 标准库函数具有或不具有该属性,因此实现具有他们自己决定什么应该或不应该用
warn_unuesd_result
标记,这就是为什么通常您必须使用(void)
转换来忽略任何调用的返回标准库函数可以完全避免任何实现中的警告。在 GCC 9.2.1、Ubuntu 19.10 中测试。
C++17
[[nodiscard]]
C++17 standardized the "return value ignored business" with an attribute.
Therefore, I hope that compliant implementations will always warn only when
nodiscard
is given, and never warn otherwise.Example:
main.cpp
compile:
outcome:
The following all avoid the warning:
I wasn't able to use
maybe_unused
directly on thef()
call:gives:
The
(void)
cast working does not appear to be mandatory but is "encouraged" in the standard: How can I intentionally discard a [[nodiscard]] return value?Also as seen from the warning message, one "solution" to the warning is to add
-Wno-unused-result
:although I wouldn't of course recommend ignoring warnings globally like this.
C++20 also allows you to add a reason to the
nodiscard
as in[[nodiscard("reason")]]
as mentioned at: https://en.cppreference.com/w/cpp/language/attributes/nodiscardGCC
warn_unused_result
attributeBefore the standardization of
[[nodiscard]]
, and for C before they finally decide to standardize attributes, GCC implemented the exact same functionality with thewarn_unused_result
:which gives:
It should be noted then that since ANSI C does not have a standard for this, ANSI C does not specify which C standard library functions have the attribute or not and therefore implementations have made their own decisions on what should or not be marked with
warn_unuesd_result
, which is why in general you would have to use the(void)
cast to ignore returns of any calls to standard library functions to fully avoid warnings in any implementation.Tested in GCC 9.2.1, Ubuntu 19.10.
此外,当验证您的代码是否符合 MISRA(或其他)标准时,静态分析工具(例如 LDRA)将不允许您调用具有返回类型的函数而不让其返回值,除非您将返回值显式转换为 (void )
Also when verifying your code complies to MISRA (or other) standards, static-analysis tools such as LDRA will not allow you to call a function that has a return type without having it return a value unless you explicitly cast the returned value to (void)