18

I have the following code in C++

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set<int> a;
    int n;

    for(int i=0;i<3;i++){
      cin>>n;
      a.insert(n);
    }

    cout << *a.end();
    return 0;
}

Why is it always printing "3" instead of the greatest element in the set? Replacing cout << *a.end(); with cout << *--a.end(); works fine.

3
  • 19
    end() is not pointing to the last element, it is pointing one past it. C++ ranges are closed at the front, open at the back: [begin, end).
    – BoBTFish
    Commented Dec 23, 2016 at 13:34
  • 5
    This std::set::end reference have a nice figure illustrating it. Commented Dec 23, 2016 at 13:38
  • I thought it was closed at the back too. Thanks! Commented Dec 23, 2016 at 13:40

5 Answers 5

60

Just use *a.rbegin() which points to the last element in the set

19
*a.end()

Undefined behaviour. In C++ iterator terminology, "end" does not mean the same thing as "last element".

Replacing cout << *a.end(); with cout << *--a.end(); works fine.

Consider a reverse iterator: *a.rbegin().

Keep in mind that both begin() and rbegin() only return dereferencable iterators if the container is not empty. For empty containers, begin() == end() and rbegin() == rend().

1
  • OMG! I always used (--a.end()), but now i know the best option ;) Commented Oct 13, 2019 at 10:12
9

Why is it always printing "3" instead of the greatest element in the set?

Because a.end() is one past the end of your vector. It doesn't hold any valid data, it's a marker for the end of your vector. As in:

for(auto i = a.begin(); i != a.end(); ++i) 
    // do stuff with i

EDIT: (thanks to Nathan) dereferencing a.end() yields the dreaded undefined behaviour. Anything could have happened: get a 3, get the last element in the set, could even have canceled X-mas!!!

1
  • 2
    May also want to say that it is UB Commented Dec 23, 2016 at 13:42
6

To find the last element of a set what we can do is use an iterator that points to last of the of the set and then decrement the iterator to reach the last element as set.end() represent the iterator that points just outside the end of set.

auto it = s.end();
it--;
cout<<(*it)<<endl;

2

For set<int>s

You can also use *prev(s.end())

Not the answer you're looking for? Browse other questions tagged or ask your own question.