为什么在将指针指向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;