为什么在将指针指向bool时有性能警告?

延长 。

当我做了这样的事情时,我觉得自己很酷:

 bool hasParent()
 {
  返回this-> parentNode;
 }

即使(布尔)演员,警告仍然没有消失。

当没有父节点时,this-> parentNode为NULL。

但是我得到:

警告C4800:'Node *':强制值为bool'true'或'false'(性能警告)

什么事情,哟? 为什么这是一个性能警告? 我认为不写这样的东西会更有效率:


 bool hasParent()
 {
  如果(this-> parentNode)
    返回true;
  其他
    返回false;
 }

但是第二个版本不会产生任何警告,编译器似乎更快乐。 哪个更快?

有关Microsoft Connect的讨论(有关在C ++中转换为bool的性能影响? )。 给微软的例子是:

 $ 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。 这是一个惩罚,用户可以select使用“int”而不是“bool”(或者更可能反之亦然)以避免“boolifying”codegen。 警告在下面的第三种情况下被抑制,因为他清楚地表明了他接受int-> bool转换的意图。

这是一个老警告,可能已经失去了它的目的,但它的行为如同这里所devise的

所以基本上MS开发人员似乎在说,如果你想“投”一个int bool你应该更正确地做到这一点,通过使用“ return this->parentNode != 0 ”,而不是隐式或显式的强制转换。

就我个人而言,我有兴趣了解更多关于警告所揭示的错误的信息。 我认为这个警告不会有很多的价值。

铸造到bool不警告消失的事实是由devise :

将expression式转换为布尔types不会禁用警告,这是devise。

我会build议MSDN的警告C4800build议的方法:

 return this->parentNode != NULL; 

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

编译器需要生成额外的代码来将指针转换为布尔值。 它基本上是一个对零的比较,并设置结果为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 

这不是从源代码直接可见的,所以编译器认为这是用户应该被警告的事情。

为什么这是一个性能警告?

编译器正在这样做:

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

成:

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

这大约需要一个时钟周期,而不是你所期望的代码。 这是一个微不足道的性能差异。

我认为最好是明确地写出!= 0 ,因为它使代码更清晰,同时也消除了警告。

写下这样会更有效率:

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

我很确定这是编译器依赖

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

 return this->parentNode != 0;