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

时间:2013-12-25 19:25:23

标签: c++ exception c++11 stack move-semantics

因此,在C ++ 11中,似乎不再需要在堆栈中对.top和.pop进行隔离。

也许我错过了一些东西,但是C ++ 03和之前的问题是如果.pop要返回一个值,那么复制操作可能会在元素复制期间抛出异常。示例(代码示例取自here):

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通过移动语义返回元素,是否有一个真正的音乐会对安全异常的关注?

1 个答案:

答案 0 :(得分:1)

在DyP的几个指针之后,这段代码应该做我在OP中要求的技巧。 由于top通过引用返回,因此可以安全地移动pop - ed。 辅助函数检查前置条件是否满足(必须是可构造的)并且希望是一个非运行操作:)

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