c ++ bool连接与| =

Soe*_*ann 4 c++ boolean

我想知道连接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)

这只是一种语法差异,还是我的错误,危险或缓慢?

Mat*_*lia 8

从注释中扩展:这里的主要区别在于您的版本始终评估右侧表达式,而具有||(或建议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)
  1. IOW,它仅在左手表达式时才评估右手表达式false; 有人指出,如果||超载,它不再短路了,仍然,在这里我不认为是这种情况 - 从我们似乎处理常规整数的上下文.

  2. 请注意,如果编译器可以证明调用state()没有可观察到的副作用(如果它只是一个内联的getter就可以轻易地完成),它可能会转换&&&或者相反,因为它具有或不具有分支isn'技术上可观察的(就C++标准而言).