堆栈弹出操作是否可以安全地返回 C++11 中的值

Could stack pop operation return the value safely in C++11

本文关键字:返回 C++11 安全 操作 是否 堆栈      更新时间:2023-10-16

因此,在 C++11 中,似乎不再需要如此严格地隔离堆栈中的 .top 和 .pop。

也许我错过了一些东西,但是 C++03 及更早版本中的问题是,如果 .pop 返回一个值,则复制操作可能会在元素复制期间引发异常。 示例(从此处获取的代码示例):

template <class T>
    // T must have default ctor and copy assignment
class Stack
{
public:
    Stack();
    ~Stack();
    Stack(const Stack&);
    Stack& operator=(const Stack&);
    unsigned Count();   // returns # of T's in the stack
    void     Push(const T&);
    T        Pop();     // if empty, returns default-
                        // constructed T
    T        Top();     // For backwards compatibility
                        // 
private:
    T*       v_;        // pointer to a memory area big
                        //  enough for 'vsize_' T objects
    unsigned vsize_;    // the size of the 'v_' area
    unsigned vused_;    // the number of T's actually
                        //  used in the 'v_' area
};

如果要执行此操作:

int main(){
  Stack<vector<double>> stack;
  fill_stack(stack); //fill stack with huge vectors
  stack.pop(); //danger of exception being throw from low memory
}

在 C++11 中,这个问题完全消失了,因为元素可以从堆栈中移动,完全消除了异常安全问题。这是在假定该元素是可移动的并且移动操作不会抛出的情况下进行的。

因此,我的问题归结为,如果 .pop 通过移动语义返回元素,是否存在真正的安全异常问题?

在 DyP 的几个指针之后,这段代码应该可以完成我在 OP 中要求的技巧。由于top通过引用返回,因此可以安全地将其从 -ed 中移出,然后立即pop -ed。帮助程序函数检查先决条件是否满足(必须是可移动的),并且希望是一个 nothrow 操作:)

template<class T>
T pull_top(std::stack<T>& x) noexcept(std::is_nothrow_move_constructible<T>::value)
{
    static_assert(std::is_move_constructible<T>::value, "pull_top requires the type to be move constructible");
    T val = std::move(x.top());
    x.pop();
    return val;
}