c++stl

Why doesn't std::queue::pop return value.?


I went through this page but I am not able to get the reason for the same . There it is mentioned that

"it is more sensible for it to return no value at all and to require clients to use front() to inspect the value at the front of the queue"

But inspecting an element from front() also required that element to be copied in lvalue. For example in this code segment

std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);
/* here temporary will be created on RHS which will be assigned to
   result, and in case if returns by reference then result will be
   rendered invalid after pop operation */
result = myqueue.front();  //result.
std::cout << ' ' << result;
myqueue.pop();

on fifth line cout object first creates a copy of myqueue.front() then assigns that to result. So, whats the difference, pop function could have done the same thing.


Solution

  • So, whats the difference, pop function could have done the same thing.

    It could indeed have done the same thing. The reason it didn't, is because a pop that returned the popped element is unsafe in the presence of exceptions (having to return by value and thus creating a copy).

    Consider this scenario (with a naive/made up pop implementation, to ilustrate my point):

    template<class T>
    class queue {
        T* elements;
        std::size_t top_position;
        // stuff here
        T pop()
        {
            auto x = elements[top_position];
            // TODO: call destructor for elements[top_position] here
            --top_position;  // alter queue state here
            return x;        // calls T(const T&) which may throw
        }
    

    If the copy constructor of T throws on return, you have already altered the state of the queue (top_position in my naive implementation) and the element is removed from the queue (and not returned). For all intents and purposes (no matter how you catch the exception in client code) the element at the top of the queue is lost.

    This implementation is also inefficient in the case when you do not need the popped value (i.e. it creates a copy of the element that nobody will use).

    This can be implemented safely and efficiently, with two separate operations (void pop and const T& front()).