【问题标题】:Incrementing Dereferenced Iterator递增解引用迭代器
【发布时间】:2016-01-25 11:00:29
【问题描述】:

我正在做 c++ 入门练习 (3.25),我正在尝试增加一个取消引用的迭代器。这是我的想法:

vector <int> arcNotas(10,0);        //hold amount of grades by 10-20-30....90-100
int notas = 0;
auto it = arcNotas.begin();
while (cin >> notas && notas!= 1000) {
    it += notas / 10;                   //move the iterator to the right position
    *it++;                              //increment the quantity of elements in that position
    it = arcNotas.begin();              //reset to the initial position
}

但是当我编译它时,编译器说(在第一个“notes”输入之后)“vector iterator not incrementable”。我正在取消引用it 专门这样做......我只是不明白出了什么问题。我进行了搜索,但我发现的只是增加it而不是*it的问题。

【问题讨论】:

  • 注意:*it++ 表示*(it++)。如果您的意思是(*it)++,那么您必须这样写:)
  • @psmears 废除++的另一个原因。
  • //将迭代器移动到正确的位置..为什么这是正确的?
  • 还要注意,arcNotas.at(notas / 10)++ 只需一行,看起来更简单。 到处使用迭代器是个坏主意。
  • @Human Helfawi 我的想法是:如果我有一个 90 级,那么把它放在向量的第 9 个对象中。这就是我的意思

标签: c++ vector iterator increment dereference


【解决方案1】:

您的问题是运算符优先级之一。简而言之,您的*it++; 行是错误的。这相当于编写*(it++),它将在先评估++ 运算符后提供旧值,然后取消引用。

相反,您要做的是首先取消引用it,然后通过写入(*it)++ 来增加值。这是因为++ 运算符的优先级高于间接运算符*

我将用一个文档化的代码示例来说明:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> grades(5, 0);
    auto it = grades.begin();

    cout << "Show initial elements before increment..." << endl;
    while(it != grades.end()) {
        cout << *it << endl;

        // operator precedence is important;
        // ++ has higher precedence than * for indirection;
        // therefore the observable side-effects are that:
        (*it)++;    // ...this increments the current element pointed by 'it'
        *it++;      // ...this causes 'it' to point to the next element after the old value has been dereferenced w/o additional side-effect
    }

    cout << endl << "Show incremented elements..." << endl;
    it = grades.begin();
    while(it != grades.end()) {
        // notice that elements have been incremented only once by this point
        // not twice as the operator precedence mistake would lead you to believe
        cout << *it << endl;
        it++;
    }

    return 0;
}

构建这个程序(GNU/Linux)的命令及其输出如下:

➜  /tmp  g++ -std=c++11 test.cpp -o test
➜  /tmp  ./test
Show initial elements before increment...
0
0
0
0
0

Show incremented elements...
1
1
1
1
1

请注意,这些值只会增加一次,而不是两次,鉴于您当前的误解,您可能已经预料到了。

【讨论】:

  • 这有点误导。后缀递增运算符返回其参数的 old 值。
  • 为了完整起见,您可能希望在*it++ 中指定取消引用的it 的旧值,而不是递增的值。即使在不使用取消引用的值时这几乎没有什么区别。
  • @n.m.:我已经更新了帖子。我认为这不一定需要投反对票。我认为从上下文中可以清楚地看出我只是在谈论说明的可观察到的副作用。
【解决方案2】:

“迭代器不可递增”消息是 运行时 错误。是您的实现对迭代器进行边界检查,并且它检测到:

it += notas / 10;

或以下it++ 导致it 超出arcNotas.end()

您应该在执行此添加之前修复您的代码以检查长度,并修复您递增迭代器而不是首先取消引用的问题。

【讨论】:

  • 没错...将向量初始化更改为 (11,0) 解决了主要问题...这是一个运行时错误。如果等级为 100,则为 v[10],而我的向量只有 [9](从零开始)。第二个问题,它的非增量是使用符号 *it=*it+1; 解决的。我不明白的是为什么...我尝试使用 *(it)++, (*it)++, ++*(it) 但它不起作用。
猜你喜欢
  • 2017-07-24
  • 2018-01-12
  • 2013-08-12
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 2013-03-23
  • 2014-05-24
相关资源
最近更新 更多