我通过这个page,但我不能得到同样的原因。这里提到的是
“更明智的做法是完全不返回值,并要求客户端使用front()检查队列前面的值。”
但是从front()检查一个元素也需要将该元素复制到lvalue中。例如,在下面的代码段中
std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);/*将在RHS上创建临时结果,并将其分配给result,如果通过引用返回,则在pop操作后result将变为无效*/
result = myqueue.front();  //result.
std::cout << ' ' << result;
myqueue.pop();在第五行,cout对象首先创建myqueue.front()的副本,然后将其赋值给result。所以,有什么不同,pop函数也可以做同样的事情。
发布于 2014-07-30 19:42:13
所以,有什么不同,
函数也可以做同样的事情。
它确实可以做同样的事情。它没有这样做的原因是,返回弹出元素的pop在存在异常的情况下是不安全的(必须通过值返回,从而创建一个副本)。
考虑这个场景(使用一个简单的/虚构的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 pop和const T& front())安全有效地实现。
发布于 2014-07-30 19:39:16
您所链接的页面回答了您的问题。
引用相关的整个章节:
人们可能会奇怪为什么
()返回value_type,而不是void。也就是说,为什么必须使用front()和pop()来检查和删除队列前面的元素,而不是将这两个元素组合在一个成员函数中?事实上,这种设计有一个很好的理由。如果pop()返回了front元素,那么它必须通过值返回,而不是通过引用返回:通过引用返回将创建一个悬空指针。然而,按值返回的效率很低:它至少涉及一个冗余的复制构造函数调用。由于pop()不可能以既高效又正确的方式返回值,因此更明智的做法是不返回值,并要求客户端使用front()检查队列前面的值。
C++在设计时考虑到了效率,超过了程序员必须编写的代码行数。
发布于 2014-07-30 19:37:59
pop不能返回对被移除的值的引用,因为它正被从数据结构中移除,那么引用应该引用什么呢?它可以通过值返回,但是如果pop的结果没有存储在任何地方呢?那么时间就浪费在了不必要的复制值上。
https://stackoverflow.com/questions/25035691
复制相似问题