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