queue::pop 现在可以返回值吗?

发布于 2025-01-03 18:15:54 字数 632 浏览 1 评论 0原文

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

  1. 异常安全:删除元素后可能会抛出一些东西
  2. 返回参考值

很好。

现在,如果我正确理解新的 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:

  1. exception safety: something might throw after removing the element
  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

入怼 2025-01-10 18:15:54

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.

好听的两个字的网名 2025-01-10 18:15:54

使用巧妙的 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.

清风不识月 2025-01-10 18:15:54

另一个问题是,并不是每个类都真正从移动中受益,即,它们可能只有一个复制者。

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

Another problem is, that not every class really benefits from moving, i.e., they might only have a copy ctor.

struct DontLikeMoves{
  // some data, whatever...
  DontLikeMoves(DontLikeMoves const& other){
    // might throw, who knows!
    // and this will even get called for rvalues
  }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文