Stroustrup and overflowing size_type in a loop

467 views Asked by At

I am reading "Programming Principles and Practices using C++" by Bjarne Stroustrup, and I would need a clarification about a surprising bit that I found in section 25.5.3. The author claims that if we want to iterate over an std::vector, then using a loop variable like

for (vector<int>::size_type i = 0; i < v.size(); ++i)

is less safe than using the iterators for the vector class:

for (vector<int>::iterator p = v.begin(); p != v.end(); ++p)

because, being of an unsigned type, i could overflow. He states that the loop using iterators has no such limitation. I am a bit confused, since I learned that size_type is guaranteed to be big enough to represent the biggest possible vector, so a variable of type size_type will never overflow in a loop like that.

EDIT

To be more specific, he presents an example using a loop variable of type int before the other two, then at the end he states:

"The size_type is guaranteed to be unsigned, so the first (unsigned integer) form has one more bit to play than the int version above. That can be significant, but it still gives only a single bit of range (doubling the number of iterations that can be done). The loop using iterators has no such limitation."

Doesn't vector<T>::size() return a vector<T>::size_type? I don't see any limitation.

2

There are 2 answers

5
AnT stands with Russia On BEST ANSWER

Well, yes, the paragraph you quoted does seem to indirecly imply or hint that size_type can be problematic. But I don't think it was the author's intent.

Note that the previous paragraph says (re: Second Edition)

So, technically, most of the loops in this book have been sloppy [...]. To avoid this problem we can use the size_type provided by vector, iterators, or a range-for-statement:

In this paragraph size_type is presented a solution for potentially problematic int loops used in the previous sections of the book. It is mentioned as a safe alternative together with iterator or range-for version of the loop.


The potential overflow (or insufficient range) problem does exist when someone tries to use std::size_t to count or index elements of a non-array-based container, like std::list, std::deque, std::map etc,, instead of using container's own size_type. But it is a slightly different story, even if it is related.

1
eerorika On

vector::size returns vector::size_type, so therefore vector::size_type i that starts from 0 can not possibly exceed maximum value representable by vector::size_type before exceeding the value returned by vector::size. It is safe.


because, being of an unsigned type, i could overflow.

If this is direct quote, then it is an error and has been fixed in the 2nd edition where i is int. In that case i might overflow.


For what it's worth, I do not find (2nd edition) the part where Bjarne claims one to be safer than the other.

He claims that iterators do not have the range limitation that the indices have. And that is true. Iterators could theoretically support infinitely large ranges.

Using size_type to loop container elements has no problem of overflowing, but The fact that container interface supports size_type in the first place effectively causes the choice of size_type to limit the range of elements that a container can contain.