queue::pop 现在可以返回值吗?
我知道 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()
等等。
I know std::queue::pop()
returns void
. For two reasons:
- exception safety: something might throw after removing the element
- to be able to return the value by reference
Fine.
Now if I understand the new C++11 move semantics correctly, the second is no longer a valid argument.
So... the only thing preventing std::queue
to have a pop
-like function returning the value lies in the possibility that the move constructor throws?
I have a hard time thinking of situations where such a move constructor would throw. Who knows of an example?
I guess the same goes for 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()
and what not.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
std::move()
可以扔进标准库的情况并不多,但也有这样的情况。例如,如果容器使用有状态分配器,它的子级也使用这个分配器,但它不会被移动到结果:这宁愿获得分配器的默认构造版本(如果我正确删除)。鉴于分配器是有状态的,这意味着无法移动对象,因此移动构造会失败并出现异常。为什么这个类型有一个移动构造函数?好吧,因为它可能是用非状态分配器实例化的,在这种情况下移动不会抛出异常。此外,一旦我们转向用户定义的类,我们就不知道在什么情况下移动它们可能会抛出异常。There aren't many cases where
std::move()
can throw in the standard library but there are cases. For example, if the container uses a stateful allocator, its children also use this allocator, but it won't be moved to a result: this would rather get a default constructed version of an allocator (if I remove correctly). Given that the allocators are stateful this means that the object can't be moved and thus the move construction fails with an exception. Why does this type then have a move constructor? Well, because it might be instantiated with non-stateful allocator in which case moving won't throw. In addition, once we move to user defined classes we have no idea under which condition moving them might throw.使用巧妙的 SFINAE 技术,确实可以为实现无抛出移动或无抛出复制的数据类型提供原子无抛出 pop_and_move()。
甚至还有一个 noexcept() 构造可以用来查看是否会抛出异常。
C++11 中扩展 SFINAE 的新概念之一是,如果主体未编译,则该函数不存在。因此可以基于 noexcept() 来实现。
我想说,为了向后兼容,该函数需要一个新名称,因此允许它与单独调用它们的现有功能共存,而不会破坏不具有允许它的语义的类型的容器。
Using clever SFINAE techniques it would indeed be possible to have an atomic non-throwing pop_and_move() for just datatypes that implement no-throwing move or no-throwing copy.
There is even a noexcept() construct available to see if something might throw.
One of the new concepts in C++11 in particular that extends SFINAE is that if the body doesn't compile the function doesn't exist. Thus one could implement based on noexcept().
I would say for backward compatibility the function would need a new name, which therefore allows it to co-exist with the existing functionality of calling them separately, not breaking containers of types that do not have the semantics to allow it.
另一个问题是,并不是每个类都真正从移动中受益,即,它们可能只有一个复制者。
Another problem is, that not every class really benefits from moving, i.e., they might only have a copy ctor.