I'm wondering about the way to concatenate bools.
What I sometimes need is to get a flag whether at least one object in a list of objects has a certain value/state/is focused etc..
What I do is this:
bool bHasState( false );
for ( auto o : MyObjectList )
{
bHasState |= ( o->state() == SOME_STATE );
}
Some of my colleagues always replace this with
bHasState = bHasState || ( o->state() == SOME_STATE );
Is this just a syntactic difference, or is my way wrong, dangerous or slow?
Expanding from the comments: the main difference here is that your version always evaluates the right-hand expression, while the version with ||
(or the proposed if
version, which is essentially the same) doesn't, as ||
has short-circuit evaluation.1
The performance difference boils down to balancing the cost of a branch (an easily predicted one, since it's going to be always taken until you find an element that makes bHasState
true
, and then always not taken) with the cost of calling state()
on every item, which may be extremely cheap (if it's a straight inline accessor, so the only cost is going to be a potential cache miss) or quite costly (if state()
isn't inline, performs more complex calculations or - say - has to acquire a busy mutex).2
Still, if you were to decide that branching at each iteration isn't going to be so costly, probably you should go one step further: just break out of the loop when you find the first item whose state matches what you are looking for
bool bHasState( false );
for ( auto o : MyObjectList ) {
if(o->state() == SOME_STATE) {
bHasState = true;
break;
}
}
as it's true that the ||
branch is going to be easily predicted, but not looping at all over irrelevant items is surely going to be faster, especially it MyObjectList
contains many elements.
Incidentally, the same exact semantic can be reproduced with this horrible standard library one-liner:
bool bHasState = std::any_of(MyObjectList.begin(), MyObjectList.end(),
[](MyObject const& o) { return o->state() == SOME_STATE; });
IOW, it evaluates the right hand expression only if the left hand expression is false
; somebody pointed out that, if ||
is overloaded, it isn't short-circuit anymore, still, here I wouldn't think this is the case - from the context we seem to be dealing with regular integers.
Notice that, if the compiler can prove that calling state()
has no observable side-effects (which can be trivially done if it's just an inline getter) it may transform the &&
to &
or the opposite as it prefers, as having or not having the branch isn't technically observable (as far as the C++ standard is concerned).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With