为什么 std::queue::pop 不返回值.?

2022-01-07 00:00:00 c++ stl

我浏览了这个页面,但我无法获得道理一样.那里提到

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

"它根本不返回任何值并要求它更明智客户端使用 front() 检查队列前端的值"

"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"

但是从 front() 检查一个元素也需要在左值中复制该元素.例如在这个代码段

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);

/* 这里临时将在 RHS 上创建,并将分配给结果,以防万一如果通过引用返回,那么结果将在弹出操作后无效 */

/* 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();

在第五行 cout 对象首先创建 myqueue.front() 的副本,然后将其分配给结果.那么,有什么区别,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.

推荐答案

那么,有什么不同,pop 函数也可以做同样的事情.

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

它确实可以做同样的事情.之所以没有,是因为在存在异常(必须按值返回并因此创建副本)的情况下,返回弹出元素的 pop 是不安全的.

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).

考虑这个场景(用一个天真的/虚构的 pop 实现来说明我的观点):

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
    }

如果 T 的复制构造函数在返回时抛出异常,则您已经更改了队列的状态(在我的幼稚实现中为 top_position)并且元素从队列中移除(并且未返回).出于所有意图和目的(无论您如何在客户端代码中捕获异常),队列顶部的元素都将丢失.

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).

这可以通过两个单独的操作(void popconst T& front())安全有效地实现.

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

相关文章