Search code examples
c++listiteratordereferencemultiset

C++ iterator reference non-exist value


I want to create two iterator p1 & p2 to keep pointing to certain elements in a multiset(or list), but weird thing is *p1 *p2 return a value NOT even in the multiset/list. And in for-loop traversal, *it behaves normally.

#include <iostream>
#include <set>

using namespace std;

class MedianFinder
{

private:
    multiset<int> orderedNums;
    int size;
    multiset<int>::iterator p1, p2;

public:
    MedianFinder() : size(0)
    {
        p1 = p2 = orderedNums.begin();
    }

    void addNum(int num)
    {
        orderedNums.insert(num);
        size++;

        cout << "p1: " << *p1 << " p2: " << *p2 << endl;

        cout << "ordered: ";
        for (multiset<int>::iterator it = orderedNums.begin(); it != orderedNums.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
};

int main()
{
    MedianFinder medianFinder;
    medianFinder.addNum(5); 
    medianFinder.addNum(7); 
    medianFinder.addNum(9); 
    return 0;
}

console output:

p1: 1 p2: 1
ordered: 5 
p1: 2 p2: 2
ordered: 5 7 
p1: 3 p2: 3
ordered: 5 7 9

both list and multiset behave the same...


Solution

  • Here

    p1 = p2 = orderedNums.begin();
    

    you make p1 and p2 equal to orderedNums.end(), because for an empty container end == begin. Dereferencing the end iterator is undefined.

    std::multiset::insert does not invalidate iterators, but that does not change the fact that p1 and p2 refer to the end of the container. They do not automagically get updated to refer to the newly inserted element.

    Your code has undefined behavior.

    Not sure what the actual aim of the code is. If you want to keep an iterator to the last element that was inserted you can store the iterator returned from std::multiset::insert.