我刚刚安装了Windows SDK v7.1(MSVC 10.0),并通过(几乎)完整警告级别(W3,qmake的CONFIG += warn_on的默认设置)运行我的代码,并对警告C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)感到惊讶

在以下代码中,streamstd::istreamtokenstd::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之间的唯一警告,因此我想知道:)

小更新:我了解警告的目的是让您知道您正在假设要进行int-> bool转换,但是1)为什么您甚至还会使用bool(主要是== typedef int)和2)为什么if(2)不能转换2无论是真还是假,我认为这是谓词的全部概念,无论是真还是假。

最佳答案


  • 流具有一个隐式转换运算符,该运算符返回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%(顺便说一句,从不担心性能问题,顺便说一句,我认为这对警告是愚蠢的)让我很高兴警告在那儿。

    此警告的解决方法是
    return 0 != <expression>
    
    <expression>是您认为应该是 bool 值的任何值。

    [1] ISTR Stroustrup编写了一个地方,如果您弄乱了运算符,那么operator bool()会静默编译:ostrm >> 5;(注意>>而不是<<)可以很好地编译,但是默默地做错了事。 (它将 bool 值转换为整数,并右移5次,然后舍弃该值。)

    09-06 04:24