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

Hon*_*onf 8 c++ stack exception move-semantics c++11

因此,似乎在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
};
Run Code Online (Sandbox Code Playgroud)

如果你这样做:

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

在C++ 11中,这个问题完全消失了,因为元素可以从栈中移出,完全消除了异常安全问题.这是因为元素是可移动的并且移动操作不会抛出.

所以,我的问题归结为,如果.pop通过移动语义返回元素,是否有一个真正的安全性异常关注音乐会?

Hon*_*onf 1

经过 DyP 的一些指导后,这段代码应该可以实现我在 OP 中要求的技巧。由于top通过引用返回,因此可以安全地将其移出并立即pop进行编辑。辅助函数检查先决条件是否满足(必须是可移动构造的)并且希望是一个无抛出操作:)

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;
}
Run Code Online (Sandbox Code Playgroud)