为什么对bool的cast指针有性能警告?

时间:2009-12-04 15:54:14

标签: c++ casting performance

Extends

当我做了类似的事情时,我以为自己很酷:

bool hasParent()
{
  return this->parentNode ;
}

即使使用(bool)演员,警告仍然不会消失。

如果没有父节点,则this-> parentNode为NULL。

但我得到了:

warning C4800: 'Node *' : forcing value to bool 'true' or 'false' (performance warning)

这是什么交易,哟?为什么这是表现警告?我认为不写下这样的东西会更有效率:


bool hasParent()
{
  if( this->parentNode )
    return true ;
  else
    return false ;
}

但第二个版本没有产生任何警告,编译器看起来更快乐。哪个更快?

7 个答案:

答案 0 :(得分:46)

有关此问题的讨论(What is the performance implication of converting to bool in C++?)。给微软的例子是:

$ cat -n t.cpp && cl -c -W3 -O2 -nologo -Fa t.cpp
1 bool f1 (int i)
2 {
3 return i & 2;
4 }
5
6 bool f2 (int i)
7 {
8 const bool b = i & 2;
9 return b;
10 }
11
12 bool f3 (int i)
13 {
14 const bool b = 0 != (i & 2);
15 return b;
16 }
t.cpp
t.cpp(3) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
t.cpp(8) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)

微软的回应(来自负责警告的开发人员)是:

  

这个警告非常有帮助,昨天我的代码中发现了一个错误。我认为马丁正在脱离背景下的“绩效警告”。

     

这不是关于生成的代码,而是关于程序员是否发出了将值从int更改为bool的意图。对此有一个惩罚,并且用户可以选择一致地使用“int”而不是“bool”(或者更可能反之亦然)以避免“boolifying”codegen。警告在下面的第三种情况下被禁止,因为他明确表示他有意接受int-> bool过渡。

     

这是一个旧的警告,可能已经超出了它的目的,但它的行为与此处设计的一样

所以基本上MS开发人员似乎在说,如果你想要“intbool投',你应该通过使用”return this->parentNode != 0“来代替隐式或显式演员。

就个人而言,我有兴趣了解警告揭示的错误类型。我认为这个警告不会有很多价值。

答案 1 :(得分:28)

投射到bool的事实并未使警告消失is by design

  

将表达式转换为bool类型不会禁用警告,这是设计使然。

我建议使用警告C4800建议的MSDN描述的方法:

return this->parentNode != NULL;

这清楚地表明,如果true不是空指针,则返回parentNode;如果false是空指针,则返回parentNode

答案 2 :(得分:8)

编译器需要生成用于将指针转换为bool的其他代码。它基本上是对零的比较,如果不是零则将结果设置为1。

00000000004005e0 <_Z4testPv>:
bool test(void* adr) {
  4005e0:       48 85 ff                test   %rdi,%rdi
  4005e3:       0f 95 c0                setne  %al
    return adr;
}
  4005f8:       c3                      retq

这不是从源代码直接可见的,因此编译器认为这是用户应该被警告的内容。

答案 3 :(得分:7)

  

为什么会出现表现警告?

编译器正在转变:

bool hasParent()
{
  return this->parentNode;
}

成:

bool hasParent()
{
  return this->parentNode != 0;
}

这比查看代码所需的时间大约一个时钟周期。这是一个微不足道的性能差异。

我认为最好明确地写出!= 0,因为这样可以使代码更清晰,也可以使警告静音。

答案 4 :(得分:2)

写作会更有效:

bool hasParent()
{
    return  this->parentNode != NULL;
}

答案 5 :(得分:1)

我很确定这是依赖于编译器的

答案 6 :(得分:0)

实际上我认为他们会优化到同样的,你也可以尝试这样做:

return this->parentNode != 0;