我知道std::queue::pop()
会返回void
。有两个原因:
精细。
现在,如果我理解新的C ++ 11正确移动语义,那么第二个不再是有效的参数。
所以...唯一阻止std::queue
有pop
函数返回值的唯一因素就是移动构造函数抛出的可能性?
我很难想到这样一个移动构造函数会抛出的情况。谁知道一个例子?
我想同样适用于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()
什么不是。
答案 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
}
};