【问题标题】:How to override *i++ for c++ custom iterator?如何为 c++ 自定义迭代器覆盖 *i++?
【发布时间】:2015-09-22 15:56:04
【问题描述】:

这让我很困惑,我正在实现一个自定义迭代器,我在这里读到:http://en.cppreference.com/w/cpp/concept/InputIterator*iter++ 的行为应该首先使用取消引用运算符,然后递增返回值(被复制),乘以 1。

我在自定义迭代器中覆盖了operator*operator++(int v),问题是当我执行operator*operator++(int v)operator* 之前被调用,这是正确的行为,但不适用于我想做(我猜?)。

如果你阅读链接,你会看到在表格的最后一行,据说如果你执行*iter++,你的实现应该首先取消引用,然后增加结果,这不是什么是默认行为。

我似乎真的不知道该怎么做,有什么想法吗?

明白答案后,标题有误导,见谅!

谢谢,

约翰

【问题讨论】:

  • 这是正确的行为
  • @PaoloM 首先,我是 C++ 初学者,所以让我提前为此道歉。什么是正确的行为?我的代码做什么或网站说什么?如问题所述,他们做不同的事情。
  • 正确的行为是operator++operator* 之前被调用。这是标准的运算符优先级。
  • 是的@PaoloM,问题是如何改变它,抱歉不清楚。
  • 你不能改变运算符的优先级,即使你可以,你当然也不应该。这会导致可怕的误导性代码。

标签: c++ iterator std


【解决方案1】:

从您提供的链接中,*i++ 相当于:

value_type x = *i; // (1)
++i;               // (2)
return x;          // (3)

也就是说,

  1. 取消引用迭代器i并将其存储在x
  2. 增加迭代器
  3. 返回值x,通过递增迭代器之前解引用。

这可以用在接受输入迭代器的模板代码中,像这样:

template <typename InputIterator, typename T>
InputIterator drop_until (InputIterator i, T const & x)
{
    while (*i++ != x);
    return i;
}

这种行为的实现通常看起来像

struct my_iterator
{
    // ...

    value_type operator * ()
    {
        // return the value that this operator is pointing to
    }

    my_iterator operator ++ (int)
    {
        my_iterator copy = *this;
        // increment *this iterator
        return copy;
    }

    // ...
};

这是可行的,因为调用 operator++(int)i++ 返回之前的迭代器值,然后该值会被取消引用,而 i 本身会递增。

要增加取消引用的值,您应该手动指定运算符优先级:

(*i)++;

由于这是 C++ 标准中定义运算符优先级的方式,因此您无法为表达式 *i++ 实现此行为,或者我猜 i 将不再是迭代器。

【讨论】:

  • 感谢您的回答,我开始觉得自己很笨......我该如何实现,以便*i++ 提供您列出的行为?我知道我可以在语句中指明运算符的优先级,但如何将其设为默认值?
  • @JohanS 哪种行为?答案开头的那个?
  • @JohanS operator*operator++ 显然是 2 不同的运算符,因此您无法通过 fixing 控制 *i++ 的行为你对operator*operator++ 的实现。这些操作的调用者有责任指定他们喜欢的顺序。
【解决方案2】:

如果你阅读链接,你会看到在表格的最后一行,如果你执行 *iter++,你的实现应该首先取消引用,然后增加结果

操作的顺序与结果无关。该站点并不是说必须按该顺序调用运算符,只是说副作用必须是等效的。网站上的示例已简化。以下具有等效的副作用,但也具有与调用 *iter++ 时这两个运算符的实际实现相同的操作顺序:

const It it_copy = i; // copying the iterator is part of post increment
++i; // increment is called first
value_type value = *it_copy; // dereference second
return value;

结果是一样的。

如果您致电*iter++,则无法获得该表中显示的订单,但您也不需要。

【讨论】:

    猜你喜欢
    • 2015-11-19
    • 1970-01-01
    • 2017-07-08
    • 2014-06-08
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多