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

新手上路,请多包涵

我浏览了这个 页面,但我无法得到同样的原因。那里提到

“更明智的做法是不返回任何值并要求客户端使用 front() 来检查队列前面的值”

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

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

在第五行 cout 对象首先创建 myqueue.front() 的副本,然后将其分配给结果。那么,有什么区别,pop 函数可以做同样的事情。

原文由 cbinder 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

那么,有什么区别,pop 函数可以做同样的事情。

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

考虑这种情况(用一个天真的/虚构的流行实现来说明我的观点):

 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 )并且该元素已从队列中删除(并且不返回)。对于所有意图和目的(无论您如何在客户端代码中捕获异常),队列顶部的元素都会丢失。

在不需要弹出值的情况下,这种实现也是低效的(即它创建了没有人会使用的元素的副本)。

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

原文由 utnapistim 发布,翻译遵循 CC BY-SA 3.0 许可协议

您链接到的页面回答了您的问题。

引用相关的整个部分:

有人可能想知道为什么 pop() 返回 void,而不是 value_type。也就是说,为什么必须使用 front() 和 pop() 来检查和删除队列前面的元素,而不是将两者组合在一个成员函数中?事实上,这种设计是有充分理由的。如果 pop() 返回最前面的元素,它必须按值而不是按引用返回:按引用返回会创建一个悬空指针。然而,按值返回是低效的:它涉及至少一个冗余的复制构造函数调用。由于 pop() 不可能以既高效又正确的方式返回值,所以更明智的是它根本不返回任何值并要求客户端使用 front() 来检查值队列的最前面。

C++ 的设计考虑到了效率,超过了程序员必须编写的代码行数。

原文由 BPF2010 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题