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