开发者

for(int i=0;i<myVector.size();++i) How many times is size() called?

开发者 https://www.devze.com 2023-04-03 02:05 出处:网络
If i have a myVector which is a STL vector and execute a loop like this: for(int i=0;i<myVector.size();++i) { ... }

If i have a myVector which is a STL vector and execute a loop like this:

for(int i=0;i<myVector.size();++i) { ... }

Does the C++ compiler play some trick to call size() only o开发者_如何转开发nce, or it will be called size()+1 times?

I am little confused, can anyone help?


Logically, myVector.size() will be called each time the loop is iterated - or at least the compiler must produce code as if it's called each time.

If the optimizer can determine that the size of the vector will not change in the body of the loop, it could hoist the call to size() outside the loop. Note that usually, vector::size() is an inline that's just a simple difference between pointers to the end and beginning of the vector (or something similar - maybe a simple load of a member that keeps track of the number of elements).

So there's actually probably little reason for concern about what happens for vector::size().

Note that list::size() could be a different story - the C++03 standard permits it to be linear complexity (though I think this is rare, and the C++0x standard changes list::size() requirements to be constant complexity).


I'm assuming that the vector doesn't change size in the loop. If it does change size, it's impossible to tell without knowing how it changes size.

On the C++ abstract machine it will be called exactly size()+1 times. And on a concrete implementation it will have an observable behaviour equivalent to it having been called size()+1 times (this is called the as if rule).

This means that the compiler can choose to call it just once, because the observable behaviour is the same. In fact, by following the as if rule, if the body of the loop is empty, the compiler can even choose to not call it at all and just skip the whole thing altogether. The observable behaviour is the same, because making your code run faster is not considered different observable behaviour.


It will be called size + 1 times. Changing the size of the vector will affect the number of iterations.


It may be called once, may be called size+1 times, or it may never be called at all. Assuming that the vector size doesn't change, your program will behave as if it had been called size+1 times.

There are two optimizations at play here: first, std::vector::size() is probably inlined, so it may never be "called" at all in the traditional sense. Second, the compiler may determine that it evaluate size() only once, or perhaps never:

For example, this code might never evaluate std::vector::size():

for(int i = 0; i < myVector.size(); ++i) { ; }

Either of these loops might evaluate std::vector::size() only once:

for(int i = 0; i < myVector.size(); ++i) { std::cout << "Hello, world.\n"; }
for(int i = 0; i < myVector.size(); ++i) { sum += myVector[i]; }

While this loop might evaluate std::vector::size() many times:

for(int i = 0; i < myVector.size(); ++i) { ExternalFunction(&myVector); }

In the final analysis, the key questions are:

  • Why do you care?, and
  • How would you know?

Why do you care how many times size() is invoked? Are you trying to make your program go faster?

How would you even know? Since size() has no visible side-effects, how would you even know who many times it was called (or otherwise evaluated)?


It will be called size() + 1 times (it may be that the compiler can recognize it as invariant in the loop, but you shouldn't count on it)


It will be called until the condition is not falsified (size() could change each time for example). If size() remains constant, it's size() + 1 times.

From the MSDN page about for:

for ( init-expression ; cond-expression ; loop-expression )
statement

cond-expression

Before execution of each iteration of statement, including the first iteration. statement is executed only if cond-expression evaluates to true (nonzero). An expression that evaluates to an integral type or a class type that has an unambiguous conversion to an integral type. Normally used to test for loop-termination criteria.


It will be called size + 1 times, as Ernest have mentioned. However, if you are sure that size is not changing, you can apply an optimisation and make your code look like this:

for (unsigned int i = 0, e = myVector.size (); i < e; ++i)

... in which case size () will be called only once.


Actually myVector.size() will be inlined, so there will be no call at all. Just comparing register value with memory location. Of course I am talking about release build.

In debug build it will be called size()+1 times.

EDIT: No doubt that there exists such compiler or STL implementation which cannot optimize myVector.size(). But the chances to face them are very low.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号