我刚刚安装了Windows SDK v7.1(MSVC 10.0)并运行了我的代码(几乎)完全警告级别(W3,默认为qmake的CONFIG += warn_on
)并且对警告C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)
感到惊讶
在以下代码中,stream
为std::istream
,token
为std::string
。
// in some function returning bool
return (stream >> token) // triggers warning c4800:
// '(void *)': forcing value to bool 'true' or 'false' (performance warning)`
// somewhere else
if( stream >> token ) // does not trigger warning c4800
这里发生了什么?我甚至不知道为什么首先触发警告。我认为第一段代码已经返回了bool
。
我理解这是挑剔,警告甚至不应该存在,但它是我的代码中唯一一个MSVC的/W3
和gcc的-Wall -pedantic
,所以我想知道:)< / p>
SMALL UPDATE :我知道警告的目的是让你知道你正在假设int-&gt; bool转换,但是 1)你为什么还要使用bool(=主要是= 为什么typedef int
和2)if(2)
不会将2
转换为真或假,我认为这是谓词的全部概念,无论是真还是假
答案 0 :(得分:5)
这里发生了什么?我甚至不知道为什么首先触发警告。我认为第一段代码已经返回了一个bool。
Streams有一个隐式转换运算符,它返回void*
。 (这是safe bool idiom的一个版本。它以这种方式完成,因为void*
编译的上下文少于bool
,因此隐式转换可能导致不需要的上下文更少。 )[1]
Streams'operator>>()
返回对其左操作数的引用 - 流。这样您就可以链接输入操作:strm >> value1 >> value2
执行为((strm >> value1) >> value2)
。
现在,当您说if( strm >> value )
时,会执行strm >> value
并返回一个流。为了将其放入if
语句,执行隐式转换为void*
,然后检查该指针是否为NULL
。
这与if(ptr)
没有区别,if
语句隐式将其条件转换为bool
,但编译器永远不会对此发出警告,因为条件不是bool
是如此常见。
使用return
,这是不同的。如果要返回某种类型,通常返回的表达式应为该类型。 VC的警告很烦人,对我来说,在100次中有99次这是多余的。但剩下的1%(从来没有一个性能问题,BTW;我认为这个警告很愚蠢)让我很高兴警告就在那里。
此警告的解决方法是
return 0 != <expression>
其中<expression>
是您认为应该被视为布尔值的任何内容。
[1] ISTR Stroustrup在某处编写operator bool()
如果你搞砸了运算符会静默编译:{{1}}(注意ostrm >> 5;
而不是>>
)会编译很好,但默默地做错了。 (它将布尔值转换为整数并右移5次,然后丢弃该值。)
答案 1 :(得分:3)
案例之间的差异可能是return
需要生成返回值,而if
不必生成任何值,而只是分支。警告显然是必须创建一个新的数据对象,因此它由return
触发,而不是由if
触发。
答案 2 :(得分:0)
如果条件被评估为零或非零,则不会转换为布尔值。
即。 if(1)不生成警告,因为1不为零。 if(true)不生成警告,因为true被评估为非零。
因此,整数,指针,布尔值都被转换为“零或非零”,而不是布尔值。
但是当您尝试从具有布尔返回的函数返回整数值时,它必须假设您想要模仿该行为。这就是为什么它表示“我假设你想要将'非零变为真,零变为假',并且你得到警告。