我想知道连接bool的方法.
我有时需要获得一个标志,是否对象列表中的至少一个对象具有某个值/状态/被聚焦等.
我这样做是:
bool bHasState( false );
for ( auto o : MyObjectList )
{
bHasState |= ( o->state() == SOME_STATE );
}
Run Code Online (Sandbox Code Playgroud)
我的一些同事总是用这个代替
bHasState = bHasState || ( o->state() == SOME_STATE );
Run Code Online (Sandbox Code Playgroud)
这只是一种语法差异,还是我的错误,危险或缓慢?
从注释中扩展:这里的主要区别在于您的版本始终评估右侧表达式,而具有||
(或建议if
版本,基本相同)的版本不会像||
短路评估那样.1
性能差异归结为平衡分支的成本(一个容易预测的分支,因为它总是会一直占用,直到你找到一个元素,bHasState
true
然后总是不被采用)与调用state()
每个项目的成本,这可能非常便宜(如果它是一个直接内联访问器,所以唯一的成本将是潜在的缓存未命中)或相当昂贵(如果state()
不是内联,执行更复杂的计算或 - 比如 - 必须获得繁忙的互斥锁).2
尽管如此,如果你决定每次迭代的分支都不会那么昂贵,那么你可能应该更进一步:当你发现第一个项目的状态与你想要的相匹配时,就跳出循环
bool bHasState( false );
for ( auto o : MyObjectList ) {
if(o->state() == SOME_STATE) {
bHasState = true;
break;
}
}
Run Code Online (Sandbox Code Playgroud)
因为||
分支很容易被预测,但是不相关的项目的循环肯定会更快,特别是它MyObjectList
包含许多元素.
顺便说一下,这个可怕的标准库单行程可以重现相同的语义:
bool bHasState = std::any_of(MyObjectList.begin(), MyObjectList.end(),
[](MyObject const& o) { return o->state() == SOME_STATE; });
Run Code Online (Sandbox Code Playgroud)
IOW,它仅在左手表达式时才评估右手表达式false
; 有人指出,如果||
超载,它不再短路了,仍然,在这里我不认为是这种情况 - 从我们似乎处理常规整数的上下文.
请注意,如果编译器可以证明调用state()
没有可观察到的副作用(如果它只是一个内联的getter就可以轻易地完成),它可能会转换&&
为&
或者相反,因为它具有或不具有分支isn'技术上可观察的(就C++标准而言).