【问题标题】:move_iterator is broken for iterators returning prvalues and returns dangling referencemove_iterator 因迭代器返回纯右值并返回悬空引用而损坏
【发布时间】:2013-12-26 15:33:10
【问题描述】:

我查看了std::move_iterator<Iterator> 的STL 源代码,发现它返回Iterator::value_type&&。当Iterator::reference 是右值并且与Iterator::value_type& 不同时,这会导致不正确的行为。

我有一个代理对象为reference 的类(如std::vector<bool>),它可以隐式转换为value_type。普通迭代器只是取消对这个代理的引用(输入迭代器要求允许这样做),但std::move_iterator 调用转换为value_type 会产生开销,然后返回对创建的临时对象的悬空引用。

std::move_iterator 出于某种原因仍然可以与std::vector<bool> 一起使用(可能是因为 bool 是一种简单类型,而悬空的bool&& 不会导致错误),但不适用于我的班级。这让我很困惑,我不明白如何修复它,我认为这是 STL 中的一个错误。

这是来自 GCC 4.8.1 的 std::move_iterator 的简化源代码:

template <typename Iterator>
class move_iterator {
public:
    typedef typename iterator_traits<Iterator>::value_type value_type;
    typedef value_type&& reference;

    reference operator*() const {
        return std::move(*it);
    }

private:
    Iterator it;
};

【问题讨论】:

  • 你的迭代器是什么类别?前向迭代器要求 referenceT&amp;T const&amp;
  • vector 不是容器,所以它也可能有特殊情况
  • 那么Iterator::value_type&amp;&amp;std::remove_reference&lt;Iterator::reference&gt;::type&amp;&amp;必须是同一类型。请注意,链接不是标准的。
  • 我说的是你的迭代器不是vector&lt;bool&gt;。您的迭代器不是 InputIterator,因此上述规则适用。
  • @lizarisk:是的,输入迭代器与其他迭代器有不同的要求,它们在这里稍微灵活一些。但是你的迭代器类型是输入迭代器吗?

标签: c++ c++11 stl iterator move-semantics


【解决方案1】:

C++ 委员会知道您遇到的问题。 LWG issue 2106 正在跟踪此问题。此问题目前处于 Open 状态,这意味着尚未决定解决方案。

更新

LWG issue 2106 及时被 C++17 接受。 PR 位于问题的底部(此更新中已更正链接)。

【讨论】:

  • 感谢您的评论!提议的决议似乎运作良好,为什么还没有被接受?
  • @lizarisk:因为从事这项工作的无偿志愿者被需要完成的工作量(除了他们的日常工作之外)压得喘不过气来。如果 LWG 2106 是他们必须处理的唯一问题,那么现在就可以完成了。我同意你的观点,目前提议的决议似乎是正确的。它经历了几次迭代才达到这一点。
  • 我在链接的文档中找不到 2106。有谁知道这个问题的解决方案是什么?
  • 谢谢,我已经更新了答案并更正了链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多