可以使用queue :: pop现在返回一个值吗?

时间:2012-02-08 10:46:15

标签: c++ stl queue c++11

我知道std::queue::pop()会返回void。有两个原因:

  1. 异常安全:删除元素后可能会抛出一些东西
  2. 能够return the value by reference
  3. 精细。

    现在,如果我理解新的C ++ 11正确移动语义,那么第二个不再是有效的参数。

    所以...唯一阻止std::queuepop函数返回值的唯一因素就是移动构造函数抛出的可能性?

    我很难想到这样一个移动构造函数会抛出的情况。谁知道一个例子?

    我想同样适用于std::stack::pop()std::vector::pop_front()std::vector::pop_back()std::deque::pop_front()std::deque::pop_back()std::list::pop_front()std::list::pop_back()什么不是。

3 个答案:

答案 0 :(得分:6)

std::move()可以抛出标准库的情况并不多,但有些情况。例如,如果容器使用有状态分配器,它的子进程也使用这个分配器,但它不会被移动到结果:这宁愿得到分配器的默认构造版本(如果我正确删除)。鉴于分配器是有状态的,这意味着对象不能被移动,因此移动构造失败并带有异常。为什么这种类型有一个移动构造函数?好吧,因为它可能用非有状态分配器实例化,在这种情况下移动不会抛出。另外,一旦我们转移到用户定义的类,我们就不知道在什么条件下移动它们可能会抛出。

答案 1 :(得分:5)

使用聪明的SFINAE技术,对于只实现无投掷移动或不投掷副本的数据类型,确实可以使用原子非抛出pop_and_move()。

甚至还有一个noexcept()构造可用于查看是否有东西可以抛出。

特别是扩展SFINAE的C ++ 11中的一个新概念是,如果正文不编译,则该函数不存在。因此,可以基于noexcept()来实现。

我想说为了向后兼容,该函数需要一个新名称,因此它允许它与分别调用它们的现有功能共存,而不是破坏没有语义允许它的类型的容器。 / p>

答案 2 :(得分:1)

另一个问题是,并非每个班级都真正受益于移动,即他们可能只有一个副本。

struct DontLikeMoves{
  // some data, whatever...
  DontLikeMoves(DontLikeMoves const& other){
    // might throw, who knows!
    // and this will even get called for rvalues
  }
};