在取消引用-*iter++之后对迭代器进行后递增.它是如何评估的

Post-incrementing an iterator after de-referencing - *iter++. How is it evaluated?

本文关键字:何评估 评估 引用 取消 iter++ 之后 迭代器      更新时间:2023-10-16

我找不到更好的标题,如果需要,请根据下面的问题进行更新。

考虑一个迭代器-iter,它指向std::vector<int>中的元素。我使用在当前迭代器位置插入*iter的值

iter = target.insert(iter, *iter);

我知道insert会将迭代器返回到新插入的元素。现在我把上面的声明改为:

iter = target.insert(iter, *iter++);

我知道这会表现得很尴尬,并导致分段错误。我不能理解的是,如何评估上述作业?我的意思是,iter在该赋值之后将指向哪个元素。据我所知,由于我使用了后增量运算符,它的行为应该与第一条语句类似,我从下面的示例赋值中推断出:

i = i++;

由于上述赋值不会影响i的值,因此*iter++的情况也应如此。

幕后的实际行为是什么?


这是真正的代码:

std::vector<int>::iterator begin = target.begin();
while (begin != target.end()) {
    if (*begin % 2 == 0) {
        begin = target.erase(begin);
    } else {
        begin = target.insert(begin, *begin); // I changed this line
        begin += 2;
    }
}

基本上,上面的代码是从向量中删除偶数元素,并复制奇数元素。

编辑:

好的,如果我将第二行更改为++begin,除了之前的更改之外,它的工作方式与当前代码相同。因此,我用以下行替换了else块中的两行:

begin = target.insert(begin, *begin++);
++begin;

因此,它似乎比前一种情况下给迭代器分配了一个过去。

所以,这就是我从这种行为中理解的:

  • *begin++首先去引用begin以获得当前位置的值
  • begin后递增
  • insert现在在后增量之后的迭代器之前插入未引用的值。因此,它不是在原始begin之前插入,而是在++begin之前插入。然后返回其插入的值++begin

我解释对了吗?

我不太理解你的问题,但为了回应你列出的理解:你的理解在特定的编译器/day/build上可能是正确的。未指定是在begin还是begin + 1处插入(这会导致从insert返回的值是两个不同的可能值之一),因为编译器可以按其喜欢的任何顺序评估insert的参数。与其试图准确地计算出会发生什么,不如将代码分割成适当的部分,使其完全清楚地表明您要做什么,并让优化器为您处理事情。几乎可以肯定的是,它被核心转储的原因是,当你增加2时,你会跳过end,永远不会检测到你已经通过了容器的末尾。

我觉得我还应该指出,"幸运的是"在函数参数的求值之后有一个序列点,或者begin = target.insert(begin, *begin++);将是未定义的行为,对begin进行两次写入,并且没有插入序列点(例如i = i++是UB)。

AFAIK您构造的target.insert(iter,*iter++)不是合法的c++,因为它会导致"未定义的行为"*iter++是合法的,从左到右计算,但没有指定函数调用的agruments的计算顺序。编写这样的表达式是一个编程错误。

准确地说,你的代码

target.insert(iter, *iter++)

给定别名

std::vector<int>::iterator cur = iter;
std::vector<int>::iterator next = iter + 1;

可以通过以下两种方式评估

targets.insert(next, *cur);
++iter;

targets.insert(cur, *cur);
++iter;

确切的版本取决于编译器、操作系统、其他代码等,通常不会指定。

虽然这是一个非常古老的问题,但我想分享我的观点,欢迎讨论。

target.insert(iter, *iter++)

该代码将对产生一些影响

  • *iter++:获取值*iter,将来调用iter++
  • 将CCD_ 28插入向量

但插入值对矢量可能有不同的影响取决于大小是否等于容量

如果size == capacity,向量需要malloc新内存并复制到新内存,因此迭代器需要更新

如果是size < capacity,矢量直接插入项。

因此返回并关注代码iter = target.insert(iter, *iter++);

如果插入导致新内存,则使用iter++将访问无效地址并导致分段错误

如果你写这样的代码:iter = target.insert(iter, *iter);,iter会一直更新,所以它是正确的

因此,如果您确信插入后大小总是小于容量,则可以使用此代码,但不建议使用