在C ++中转换为bool的性能影响是什么?
[这个问题与这个问题有关,但不一样。]
我的编译器警告将某些types隐式转换或转换为bool,而显式转换不会产生警告:
long t = 0; bool b = false; b = t; // performance warning: forcing long to bool b = (bool)t; // performance warning b = bool(t); // performance warning b = static_cast<bool>(t); // performance warning b = t ? true : false; // ok, no warning b = t != 0; // ok b = !!t; // ok
这是与Visual C ++ 2008,但我怀疑其他编译器可能有类似的警告。
所以我的问题是:铸造/转换到bool
的性能意味着什么? 在某些情况下,明确的转换是否具有更好的性能(例如,对于某些目标体系结构或处理器)? 隐式转换以某种方式混淆了优化器?
微软对他们警告的解释并不特别有用。 他们暗示有一个很好的理由,但他们不解释。
我对这种行为感到困惑,直到我find这个链接:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99633
显然,来自微软开发者“拥有”这个警告:
这个警告是非常有帮助的,昨天我的代码中发现了一个错误。 我认为马丁正在脱离上下文的“性能警告”。
这不是关于生成的代码,而是关于程序员是否已经意图将int值更改为bool 。 这是一个惩罚,用户可以select使用“int”而不是“bool”(或者更可能反之亦然)以避免“boolifying”codegen。 […]
这是一个老警告,可能已经失去了它的目的,但它的行为如同这里所devise的。
所以在我看来,警告更多的是风格,避免一些错误。
希望这会回答你的问题…
😛
performance完全相同。 它涉及x86上的几个指令,其他一些架构上可能有3个指令。
在x86 / VC ++上,他们都这样做
cmp DWORD PTR [whatever], 0 setne al
海湾合作委员会生成同样的事情,但没有警告(在任何警告级别)。
性能警告确实有一点意义。 我也有过,我的好奇心使我跟反汇编进行调查。 它试图告诉你,编译器必须生成一些代码来强制值为0或1.因为你坚持一个布尔,老的C的想法0或其他任何东西不适用。
如果你真的想要的话,你可以避免这种小小的performance。 最好的方法是完全避免演员阵容,从一开始就使用布尔。 如果你必须有一个int,你可以使用if(int)而不是if(bool)。 生成的代码将只检查int是否为0。 没有额外的代码,以确保如果它不是0的值是1将被生成。
听起来像我过早的优化。 你是否期望演员的表演能够严重影响你的应用的performance? 也许如果你正在编写内核代码或设备驱动程序,但在大多数情况下,他们都应该没问题。
据我所知,其他任何编译器都没有这个警告。 唯一的办法,我可以认为这会导致性能的损失是编译器必须比较整个整数为0,然后适当地分配布尔(不像一个转换,如一个字符布尔,结果可以复制,因为bool是一个字节,因此它们实际上是相同的),或者是一个整数转换,它涉及将某些或全部源复制到目的地,如果它大于源(就内存而言) 。
对于什么是良好的代码,这是微软的另一个无用和无益的想法,并且导致我们不得不忍受这样的愚蠢的定义:
template <typename T> inline bool to_bool (const T& t) { return t ? true : false; }
long t; bool b; int i; signed char c; ...
如果bool不要求为0或1,那么当你做任何“免费”的事情时,你会得到一个警告。b = !! t有效地分配(语言内置的,不可重写的) bool operator!(long)
你不应该指望! 或者!=运算符即使使用优化编译器也要花费零个asm指令。 int i = t通常是完全正确的。 甚至签了字符c = t; (在x86 / amd64上,如果t在%eax寄存器中,在c = t之后,使用c只是表示使用%al。amd64对每个寄存器都有字节寻址,BTW。IIRC,在x86中有些寄存器没有字节寻址。)
无论如何, b = t; i = b
; isn't the same as
c = t; i = c;
it's i = !!t; instead of i = t & 0xff b = t; i = b
; isn't the same as
c = t; i = c;
it's i = !!t; instead of i = t & 0xff b = t; i = b
; isn't the same as
c = t; i = c;
it's i = !!t; instead of i = t & 0xff ;
呃,我想大家已经知道了以前的答复。 我的观点是,这个警告对我来说是有意义的,因为它捕获了编译器必须做的事情,你没有真正告诉它的事情,就像!! BOOL返回,因为你声明了函数bool,但返回一个整数值这可能是真实的,!= 1。例如,很多窗口的东西返回BOOL(INT)。
这是MSVC的一些G ++没有的警告之一。 我已经习惯了g ++,而且它肯定会警告MSVC没有的东西,但是我很高兴告诉了我。 我为我使用的MFC / Win32类/macros/函数写了一个portab.h头文件。 这就得到了我正在使用的我的GNU / Linux机器上(和cygwin)编译的MFC应用程序。 我主要希望能够对我在家工作的东西进行编译testing,但是最终我发现g ++的警告非常有用。 对于例如模板也要严格一些
在一般的布尔,我不知道它作为一个返回值和parameter passing使用更好的代码。 即使对于本地人来说,g ++ 4.3似乎也没有发现,在分支它之前,它不必强制为0或1。 如果它是一个局部variables,并且你永远不会得到它的地址,那么编译器应该保持它的最大速度。 如果它必须从寄存器溢出到堆栈,它可以保持在4个字节,因为这可能会稍微快一点。 (在加载/存储(非本地)布尔时,它使用了很多movsx(符号扩展)指令,但我不记得自动(本地堆栈)variables的作用,我记得看到它保留了一个奇数在有一些bools当地人的函数中堆栈空间的数量(不是4的倍数)。
使用bool标志比去年的Digital Mars D编译器的int要慢: http : //www.digitalmars.com/d/archives/digitalmars/D/opEquals_needs_to_return_bool_71813.html (D很像C ++,但放弃了完整C向后compat来定义一些很好的新语义,以及对模板元编程的很好的支持,例如“static if”或“static assert”,而不是模板hack或者cppmacros,我真的想给D试一下。
对于数据结构来说,它是有意义的,例如,如果你想在一个int之前打包一些标志,然后在结构中有一些双打,你将会有很多。
根据你对MS的解释的链接,看起来如果这个值只是 1或者0,那么没有性能影响,但是如果在编译的时候需要build立一个比较的话,是否有其他的非0值呢?
在C ++中,只有两个值的bool ISA int 0 = false,1 = true。 编译器只需要检查一个位。 为了清楚,真正的!= 0,所以任何int可以覆盖布尔,它只是花费处理周期来这样做。
通过在代码示例中使用long,您将强制执行更多的检查操作,这将导致性能下降。
不,这不是不成熟的优化,使用代码需要更多的处理时间是非常疯狂的。 这只是很好的编码练习。
除非你正在为一个非常关键的内部循环(模拟器内核,光线追踪器等)编写代码,否则在这种情况下不必担心任何性能问题。 在你的代码中还有其他更重要的事情需要担心(还有其他更重要的性能陷阱,我敢肯定)。
微软的解释似乎是他们想说的是:
嘿,如果你使用的是一个int,但只存储真或假的信息,使其成为一个布尔!
我怀疑在性能方面能获得多less,但是MS可能会发现有一些收益(无论如何它们的使用)。 微软的代码往往会运行很多,所以也许他们发现微型优化是值得的。 我相信MS编译器的一个公平点是支持他们自己觉得有用的东西(只有有意义,对吗?)。
而你摆脱了一些肮脏,小铸造启动。
这里我不认为performance是问题。 你得到一个警告的原因是信息在从int到bool的转换过程中丢失了。