堆栈是否有一个异常安全的方法来返回和删除带有移动语义的顶部元素?

Mot*_*tti 10 c++ exception-safe move-semantics c++11

在回答一个关于std::stack::pop() 我声称原因pop没有返回的问题的原因是出于异常安全原因(如果复制构造函数抛出会发生什么).

@Konrad评论说现在有了移动语义,这已经不再适用了.这是真的?

AFAIK,移动构造函数可以 throw,但也许与noexcept它一起仍然可以实现.

对于奖励积分,此操作可以提供哪些线程安全保证?

sel*_*tze 3

当然,并非每种类型都支持移动,C++0x 甚至允许抛出移动构造函数。只要从右值构造对象可能会抛出异常,它就不可能是异常安全的。然而,移动语义允许您拥有许多在给定右值源的情况下不可抛出构造的类型。

SFINAE 可以对此提供有条件的支持。但即使没有这样的条件成员函数,也没有什么能阻止你编写:

auto stack = ...;
auto elem = std::move_if_noexcept(stack.back());
stack.pop_back();
Run Code Online (Sandbox Code Playgroud)

即使您的移动构造函数没有提供强有力的保证,这也可以提供强有力的异常保证。

  • @Motti:问题是,根据存储的对象是否具有移动构造函数,您将拥有不同的接口和行为(而不仅仅是实现),因此这并不是一个好主意。 (4认同)
  • @dribeas:如果有一个移动构造函数,那么有一个 pop 函数会返回一些东西,如果没有,则返回 void 会不会很糟糕?在常见的用例中,要么您知道堆栈的值类型(例如,如果它是“int”,您可以使用返回值,如果您在不应该使用返回值时您的代码无法编译),或者您正在编写通用代码并且不知道类型(在这种情况下您坚持使用旧界面)。 (2认同)