铸造到'void'真的有什么作用?

时间:2015-12-15 12:06:21

标签: c++ casting compiler-warnings void suppress-warnings

(void)x;这样经常使用的语句允许禁止有关未使用的变量x的警告。但是如果我尝试编译以下内容,我会得到一些我不太明白的结果:

int main()
{
    int x;
    (short)x;
    (void)x;
    (int)x;
}

使用g ++编译,我收到以下警告:

$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
     (short)x;
             ^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
     (int)x;
           ^

因此,我得出结论,转换为void与转换为任何其他类型非常不同,目标类型与decltype(x)相同或不同。我猜测可能的解释是:

  • (void)x;只是一种惯例,但其他演员不会抑制警告。所有陈述同样没有任何效果。
  • 这种差异在某种程度上与void x;short x;时不是有效陈述的事实有关。

哪些更正确?如果没有,那么如何解释编译器警告的差异?

4 个答案:

答案 0 :(得分:31)

Casting to void用于禁止编译器警告。 Standard在§5.2.9/ 4中说,

  

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

答案 1 :(得分:10)

本声明:

(void)x;

说“忽略x的值。”没有void这样的类型 - 缺少类型。所以它与此截然不同:

(int)x;

其中说“将x视为整数”。当忽略结果整数时,会收到警告(如果已启用)。

当你忽略一些什么都不是的东西时,它不被GCC认为是一个问题 - 并且有充分的理由,因为转换为void是在C和C ++中显式忽略变量的惯用方法。

答案 2 :(得分:4)

该标准不要求对未使用的局部变量或函数参数生成警告("诊断"标准)。同样,它也没有强制要求如何抑制这种警告。将变量表达式转换为void以抑制此警告已经成为C和后来的C ++社区中的一个习惯用语,因为结果不能以任何方式使用(例如(int)x除外),因此它&#39 ;不太可能缺少相应的代码。 E.g:

(int)x;  // maybe you meant f((int)x);
(void)x; // cannot have intended f((void)x);
(void)x; // but remote possibility: f((void*)x);

就个人而言,我发现这个约定仍然模糊不清,这就是为什么我更喜欢使用函数模板:

template<typename T>
inline void ignore(const T&) {} // e.g. ignore(x);

忽略函数参数的惯用方法是省略其名称(如上所示)。我需要经常使用此函数,因为我需要能够在有条件编译的代码中命名函数参数,例如assert。我发现例如以下比使用#ifdef NDEBUG更清晰:

void rate(bool fantastic)
{
    assert(fantastic);
    ignore(fantastic);
}

答案 3 :(得分:0)

可能的用途:

auto it = list_.before_begin();
for (auto& entry : list_)
{
    (void)entry; //suppress warning
    ++it;
}

现在迭代器“ it”指向最后一个元素