【问题标题】:Can queue::pop return a value now?queue::pop 现在可以返回值吗?
【发布时间】:2012-02-29 19:08:11
【问题描述】:

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

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

很好。

现在,如果我正确理解了新的 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() 和其他情况也是如此。

【问题讨论】:

  • 这确实是两个问题。投掷移动构造函数和返回 pop 的示例。
  • 我需要一个投掷移动构造函数的例子来理解为什么我们不能返回pop
  • 那些根本没有移动构造函数的类型呢?
  • 好吧,由于并非所有类型都可以有效移动,所以第二个原因仍然有效。仅仅在语言中添加移动语义并不能使所有按值返回性能明智的无操作,它是关于使用它们的类型来发挥它们的优势,并不是所有类型都可以做到这一点。第一个原因,在实践中可以想到哪些情况,以及标准允许哪些情况,some some时间点could 可能想出两个不同的东西。

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


【解决方案1】:

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

【讨论】:

  • 你最终给了这么多问题一个有趣的转折。有一天,当我有时间时,我会浏览您的个人资料并阅读您对所有问题的所有答案。
【解决方案2】:

使用巧妙的 SFINAE 技术,确实可以为实现不扔移动或不扔复制的数据类型提供原子不扔 pop_and_move()。

甚至还有一个 noexcept() 构造可用于查看是否会抛出异常。

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

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

【讨论】:

  • 您能否详细说明 SFINAE 在 C++11 中的扩展(标准参考会很好)?我根本没有听说过,想了解更多。
  • Alexandrescu 在 Going Native 会议上关于可变参数模板的演讲中提到了这一点。作为“替换失败不是错误”原则的一部分,如果主体不能编译,这也被认为是替换失败(因此忽略这个专业化)。使用 noexcept() 可能已经创建了一个函数,该函数将在可用且未抛出时使用 move,然后在可用且未抛出时将使用 copy 作为第二选择,否则无法编译。
  • 听起来很有希望!这个答案不是对我的问题最直接的答案,但它实际上是我在不知不觉中寻找的。​​span>
  • 讲座可在 msdn channel9 上找到。 channel9.msdn.com/Events/GoingNative/GoingNative-2012 特别关注 Alexandrescu 的演讲。 (可变参数模板非常复杂,静态的如果稍微少一点,但它会向您展示他们能够根据模板参数将什么放入库中,即使没有概念作为语言特性)。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2014-09-22
    • 1970-01-01
    • 2013-08-14
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多