-2

The const reference returned by priority_queue's top() changes after calling pop() (visual studio 2015)

priority_queue<int> queue;
queue.push(1);
queue.push(2);
queue.push(3);

const int & m = queue.top();
cout << m << endl; // 3
queue.pop();
cout << m << endl; // 2
queue.pop();
cout << m << endl; // 1

If get top value by auto & m = queue.top();, then output is also 3 2 1.

While if get top value by auto m = queue.top();, then output is 3 3 3.

What's mechanism behind this ?

Richard Critten
  • 2,138
  • 3
  • 13
  • 16
stanleyerror
  • 728
  • 1
  • 9
  • 23

1 Answers1

1

If get top value by auto & m = queue.top();, then output is also 3 2 1.

Despite it is calling undefined behavior to use m after the 1st pop() call, it is likely that the next value is moved to that dangling reference (address). That is because the default underlying type of std::priority_queue is std::vector, which guarantees a contiguous array of elements.

But as mentioned that behavior is undefined, and there are no guarantees to reproduce that result with a different compiler.

While if get top value by auto m = queue.top();, then output is 3 3 3.

The value from top is stored into m once, and never changed afterwards.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • why wouldn't the const reference `m` prolong the return value's lifetime? (because the return type is `const int &` rather than `int`?) – stanleyerror Nov 12 '16 at 13:08
  • @stanleyerror In the [documentation](http://en.cppreference.com/w/cpp/container/priority_queue/top) it's said _"... Returns reference to the top element in the priority queue. This element will be removed on a call to pop()."_ – πάντα ῥεῖ Nov 12 '16 at 13:18
  • 1
    @stanleyerror you're thinking of when a reference is bound to a prvalue. However `top()` returns an lvalue , not a prvalue (another way to say that is, it returns by reference , not by value). There is no temporary involved. – M.M Nov 12 '16 at 13:38