120
int fn();

void whatever()
{
    (void) fn();
}

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

跟进:

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

如果有虫子因此逃跑,我会吃掉我的话......

4

9 回答 9

86

大卫的回答几乎涵盖了这样做的动机,明确地向其他“开发人员”展示你知道这个函数返回但你明确地忽略它。

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

我认为对于 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.
于 2009-03-27T13:12:34.150 回答
48

在工作中,我们使用它来确认函数具有返回值,但开发人员已断言忽略它是安全的。由于您将问题标记为 C++,因此您应该使用static_cast

static_cast<void>(fn());

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

于 2009-03-27T13:03:49.257 回答
39

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

它分析代码以寻找可能的问题并发出警告和建议。如果函数返回了一个未检查的值,lint则会发出警告以防意外。lint要对此警告保持沉默,请将呼叫发送到(void)

于 2009-03-27T13:13:13.510 回答
24

转换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);

它也可以。

于 2011-08-23T12:11:47.997 回答
9

从 c++17 开始,我们有了[[maybe_unused]]可以用来代替强制转换的属性void

于 2018-12-23T19:36:50.720 回答
4

铸成无效是无成本的。它只是编译器如何处理它的信息。

于 2009-03-27T13:05:18.240 回答
4

对于您将程序转换为 void 的功能是没有意义的。我还认为你不应该使用它来向正在阅读代码的人发出信号,正如大卫在回答中所建议的那样。如果您想就您的意图传达一些信息,最好使用评论。添加这样的演员只会看起来很奇怪,并会引发有关可能原因的问题。只是我的观点...

于 2009-03-27T13:16:41.690 回答
1

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

于 2015-03-20T20:59:25.897 回答
0

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 中测试。

于 2020-05-08T09:09:30.497 回答