6

I have a vector:

std::vector<int> vec = {1, 2, 3};

And I want to make a reverse for loop. It works, when I write:

for(int i = vec.size() - 1; i >= 0; --i) {
    std::cout << i << std::endl; // 2, 1, 0
}

But I get a very large number (like 18446744073709223794) if I write:

for(size_t i = vec.size() - 1; i >= 0; --i) {
    std::cout << i << std::endl;
}

But they both work when I write:

for(int i = 0; i < vec.size() - 1; ++i) {
    std::cout << i << std::endl; // 1, 2, 3
}

// Or
for(size_t i = 0; i < vec.size() - 1; ++i) {
    std::cout << i << std::endl; // 1, 2, 3
}

Why do I get the wrong size of the vector when I use size_t?

I think there is a problem with the conversion.

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
asd
  • 257
  • 5
  • 15

2 Answers2

9

Let the compiler tell you what's wrong!

If you compiled your program with warnings enabled, the compiler would tell you something like this:

<source>: In function 'int main()':

7:43: warning: comparison of unsigned expression in '>= 0' is always true [-Wtype-limits]
    7 |     for(std::size_t i = vec.size() - 1; i >= 0; --i) {
      |                                         ~~^~~~

Why is that? It's because std::size_t is an unsigned type in C++; it only represents non-negative numbers. Read more about turning on warnings and why it's important: Why should I always enable compiler warnings?

So, how should we reverse-iterate?

I've decided to split my answer here off to a separate question, independent of OP's bug. Please go read it.

einpoklum
  • 102,731
  • 48
  • 279
  • 553
  • Thank you for a great answer. Why you use in option 1 `std::crbegin` and `std::crend` is there will be any difference If I use `std::rbegin` and `std::rend`? – asd Jun 13 '20 at 09:50
  • @SKIP: `crbegin()` and `crend() gives you `vector::const_iterator`s, guaranteeing you wont change the vector's content through the iterator. – einpoklum Jun 13 '20 at 10:03
6

The problem is that size_t is an unsigned integer, i.e. it can only have positive values. When you decrease 0 for an unsigned type an underflow happens and the result is usually the largest integer representable by that type, e.g. 18446744073709223794 in your case. Finally the check for i >= 0 is always true for any unsigned type and your loop will never terminate.

Haatschii
  • 8,651
  • 10
  • 56
  • 93