[此问题与this one有关但不一样。]
我的编译器警告隐式转换或将某些类型转换为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
的性能影响是什么?在某些情况下(例如,对于某些目标体系结构或处理器),显式转换是否具有更好的性能?隐式转换是否会以某种方式混淆优化器?
微软explanation的警告并不是特别有帮助。他们暗示有充分的理由,但他们没有解释。
答案 0 :(得分:36)
我对这种行为感到困惑,直到找到这个链接:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99633
显然,来自微软开发人员“拥有”此警告:
这个警告令人惊讶 很有帮助,并在我的代码中发现了一个错误 就在昨天。我认为马丁是 采取“绩效警告” 上下文。的
的这与生成的代码无关, 这是关于是否 程序员已发出意图 将值从int更改为bool 。 对此有惩罚,并且 用户可以选择使用“int” 而不是“bool”一致(或 更可能反之亦然)避免 “boolifying”codegen。 [...]
这是一个旧警告,可能有 它的目的已经过时了,但确实如此 表现得像这里设计的那样。
所以在我看来,警告更多的是关于风格和避免一些错误。
希望这会回答你的问题...
: - P
答案 1 :(得分:12)
整体表现完全相同。它涉及到x86上的一些指令,在其他一些架构上可能有3个指令。
在x86 / VC ++上,它们都是
cmp DWORD PTR [whatever], 0
setne al
GCC生成相同的内容,但没有警告(在任何警告级别)。
答案 2 :(得分:5)
性能警告实际上确实有点意义。我也有它,我的好奇心导致我与反汇编者一起调查。它试图告诉你编译器必须生成一些代码来强制将值强制为0或1.因为你坚持使用bool,旧学校C的0或其他任何东西都不适用。
如果你真的想要,你可以避免这种微小的性能损失。最好的方法是完全避免演员阵容并从一开始就使用bool。如果你必须有一个int,你可以使用if(int)而不是if(bool)。生成的代码将简单地检查int是否为0。如果不是0,则没有额外的代码来确保值为1。
答案 3 :(得分:3)
据我所知,任何其他编译器都没有警告。我认为这会导致性能损失的唯一方法是编译器必须将整个整数与0进行比较,然后适当地分配bool(不像char这样的转换到bool,结果可以复制,因为bool是一个字节,所以它们实际上是相同的),或者是一个整体转换,它涉及将一些或所有源复制到目的地,可能在目的地为零之后,如果它大于源(就内存而言)
这是微软关于什么构成优秀代码的无用且无益的想法中的另一个,并且导致我们不得不忍受这样的愚蠢定义:
template <typename T>
inline bool to_bool (const T& t)
{ return t ? true : false; }
答案 4 :(得分:3)
听起来像是对我过早优化。您是否期望演员阵容的表现会严重影响您的应用程序的性能?也许如果您正在编写内核代码或设备驱动程序,但在大多数情况下,它们都应该没问题。
答案 5 :(得分:1)
long t;
bool b;
int i;
signed char c;
...
如果bool不需要为0或1,那么当你做任何“免费”的事情时会收到警告.b = !! t有效地分配了结果(内置语言,不可覆盖) )bool operator!(long)
你不应该期待!或!=运算符即使使用优化编译器也要花费零asm指令。通常,int i = t通常是完全优化的。甚至签名char c = t; (在x86 / amd64上,如果t在%eax寄存器中,在c = t之后,使用c只意味着使用%al.amd64对每个寄存器都有字节寻址,BTW。IIRC,在x86中有些寄存器没有字节寻址。)
无论如何,b = t; i = b
; ; isn't the same as
instead of i = t & 0xffc = t; i = c;
it's i = !!t;
呃,我想每个人都已经知道以前回复的所有内容。我的观点是,这个警告对我来说很有意义,因为它抓住了编译器必须执行你没有真正告诉它的事情的情况,比如!! BOOL返回因为你声明了函数bool,但是返回一个整数值这可能是真的!= 1.例如很多windows东西都返回BOOL(int)。
这是MSVC的一些警告,G ++没有。我更习惯于g ++,它肯定会警告MSVC没有的东西,但我很高兴它告诉我。我写了一个portab.h头文件,其中包含我使用的MFC / Win32类/宏/函数的存根。这得到了MFC应用程序,我正在家里(和cygwin)在我的GNU / Linux机器上编译。我主要希望能够编译测试我在家里工作的东西,但我最终发现g ++的警告非常有用。关于例如,它也更严格模板...
一般来说,在bool上,当用作返回值和参数传递时,我不确定它是否会产生更好的代码。即使对于本地人来说,g ++ 4.3似乎也没有弄清楚它在分支之前不必将值强制为0或1。如果它是一个局部变量并且你从不接受它的地址,那么编译器应该保持它的最大值。如果它必须将它从寄存器溢出到堆栈,它也可以保持4个字节,因为它可能稍快一些。 (它在加载/存储(非本地)bool时使用了很多movsx(符号扩展)指令,但我真的不记得它为自动(本地堆栈)变量做了什么。我记得看到它保留了一个奇数在具有一些bools locals的函数中的堆栈空间量(不是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”而不是模板hacks或cpp宏。我真的喜欢在某个时候给D试一试。:)
对于数据结构,它可能有意义,例如如果你想在一个int之前打包几个标志,然后在一个结构中加一些你会有相当多的。
答案 6 :(得分:0)
根据您对MS'解释的链接,似乎如果值仅 1或0,则没有性能损失,但如果它是任何其他非-0必须在编译时建立比较的值?
答案 7 :(得分:0)
在C ++中,bool ISA int只有两个值0 = false,1 = true。编译器只需检查一位。要完全清楚,真的!= 0,所以任何int都可以覆盖bool,它只需要花费处理周期。
通过在代码示例中使用long,您将强制进行更多位检查,这将导致性能损失。
不,这不是过早的优化,使用需要更多处理时间的代码是非常疯狂的。这只是很好的编码实践。
答案 8 :(得分:0)
除非你为真正的关键内部循环(模拟器核心,光线跟踪器等)编写代码,否则在这种情况下担心任何性能命中都没有意义。在你的代码中还有其他更重要的事情需要担心(潜在的其他更重要的性能陷阱,我敢肯定)。
答案 9 :(得分:0)
微软的解释似乎是他们试图说的是:
嘿,如果你正在使用int,但是 只存储真假信息 它,让它成为一个布尔!
我对在性能方面获得多少会产生怀疑,但MS可能已经发现有一些收获(无论如何)。微软的代码往往运行得非常多,所以也许他们发现微优化是值得的。我相信MS编译器的一些功能是支持他们自己觉得有用的东西(只是有道理,对吧?)。
你摆脱了一些肮脏的小演员阵容。
答案 10 :(得分:-1)
我不认为表演是问题所在。您收到警告的原因是在从int转换为bool期间信息丢失。