-5

This is code I have written:

multiset<int>S;
for(int i = 0;i<20;i++)
S.insert(i);
for(auto it = S.end();it!=S.begin();--it)
cout<<*it<<" ";
cout<<endl;

Output:

20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 
Chad
  • 18,706
  • 4
  • 46
  • 63
user3778989
  • 127
  • 1
  • 2
  • 8

3 Answers3

2

Your code contains some undefined behavior. As you already indicated S will contain all values from 0 till 20 (exclusive), though somehow the printing gives 1 til 20 (inclusive).

Your code:

for(auto it = S.end();it!=S.begin();--it)
    cout<<*it<<" ";

The problem here is that the range [begin, end) has end referring to something which ain't part of the set. Dereferencing the iterator received from end() can crash your program or let it produce some random value. In this case, I guess you get the value 20 because of compiler optimizations. (Some black box optimization)

In C++ (and other languages), the concept of iterators is accompanied by a concept of reverse iterators. (If you follow the link, there is a nice picture explaining the iterators.)

Basically, using the reverse iterators will allow you to loop from the back to the beginning as if you were looping with normal iterators:

for (auto it = S.crbegin(); it != S.crend(); ++it)
     cout << *it << " ";

Note that the rbegin() and crbegin() don't have any disadvantages for code complexity. (unless you want to transform them to a forward iterator again)

Bonus: By default, don't use the -- operator on iterators, it gives headaches when trying to debug.

JVApen
  • 11,008
  • 5
  • 31
  • 67
1

The loop with the iterator is incorrect and has undefined behavior because the iterator returned by the member function end() is dereferenced in the loop.

A valid program can look like

#include <iostream>
#include <set>

int main() 
{
    std::multiset<int> s;

    for ( int i = 0; i < 20; i++ ) s.insert( i );

    for ( auto it = s.end(); it != s.begin(); ) std::cout << *--it << " ";
    std::cout << std::endl;

    return 0;
}

Its output is

19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 

Of course you could use the reverse iterator of the class returned by the function rbegin(). For example

#include <iostream>
#include <set>

int main() 
{
    std::multiset<int> s;

    for ( int i = 0; i < 20; i++ ) s.insert( i );

    for ( auto it = s.rbegin(); it != s.rend(); ++it ) std::cout << *it << " ";
    std::cout << std::endl;

    return 0;
}

In this case the loop looks simpler.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
-2

Better use:

for(auto it = S.rbegin(); it != S.rend(); ++it)

update according to comments.

BruceSun
  • 144
  • 9