为什么.end()可以返回无效的迭代器,而不是每次都进行求值(如.size())并检查它是否';它仍然有效吗? 我最近在C++中了解了迭代器失效。我不明白为什么for循环中的.end()函数会返回无效的迭代器,因为它是for循环,每次循环运行时都会导致对.end()的函数调用,就像基于索引的for循环使用.size()时一样

为什么.end()可以返回无效的迭代器,而不是每次都进行求值(如.size())并检查它是否';它仍然有效吗? 我最近在C++中了解了迭代器失效。我不明白为什么for循环中的.end()函数会返回无效的迭代器,因为它是for循环,每次循环运行时都会导致对.end()的函数调用,就像基于索引的for循环使用.size()时一样,c++,C++,引擎盖下有什么缓存吗?不是每次都调用.end()?如果.end()函数将检查迭代器在上一次循环迭代中是否已更改,那么我们是否可以修复无效的迭代器 发生了什么,最重要的是,为什么会有差异(使用.size()) 我必须显式更新迭代器的示例代码: std::vector<int> v {0, 1, 2, 3, 4, 5}; for (auto it = v.begin(); it != v.end(); ++it) { if (*it == 5 && std::ne

引擎盖下有什么缓存吗?不是每次都调用
.end()
?如果
.end()
函数将检查迭代器在上一次循环迭代中是否已更改,那么我们是否可以修复无效的迭代器

发生了什么,最重要的是,为什么会有差异(使用
.size()

我必须显式更新迭代器的示例代码:

std::vector<int> v {0, 1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); ++it) {
    if (*it == 5 && std::next(it) == v.end()) {
        v.resize(v.size() + 1);
        it = std::next(v.begin(), v.size() - 2);
        *std::next(it) = 999;
        *it = 0;
    }
}

更新:感谢您在回答和评论中的解释。使迭代器无效的不是
.end()
函数。整个
It
对象是无效的,我不知何故忽略了一个事实,即for循环中的begin语句,
autoit=v.begin()
不是在每次迭代之前完成的。从逻辑上考虑,一个循环怎么可能工作呢…

基本上
std::vector
是一个动态分配的数组
int*
的包装器。让我们看看如何迭代一个数组。

我们可以使用大小进行迭代。这里的
6
对应于您的代码中的
v.size()

现在,当我们调整数组大小时,我们分配新内存并复制数据,释放旧内存并重新分配指向新内存区域的指针:

int *v = new int[6]{0, 1, 2, 3, 4, 5};
for (int *it = v; it != v + 6; ++it) {
    if (*it == 5 and it + 1 == v + 6) {
       // resize
       {
          int *temp = new int[7]; // allocate new array
          std::copy(v, v + 6, temp); // copy elements
          delete[] v; // delete old array
          v = temp; // reassign pointer
       }
       // Oops! `it` points into `v` that was `delete[]`d above!
    }
}
delete[] v;

由于旧数组已被删除,指针
it
无效,它指向一个已释放的内存。

如果您可以在问题中包含一个说明您的问题的值,这会有所帮助。这是一个被调用的函数。我不清楚你在问什么。使用示例代码
更新。end()
不会返回无效的迭代器,它会返回无法取消引用的有效迭代器,因为它超过了最后一个有效元素。第二个代码在循环每次迭代时调用
size()
,就像
end()
一样。所以我不知道你在这里期望什么。为什么for循环没有检测到v在下一个循环发生时发生了变化?
for循环没有检测到
我想我不明白-for循环是一种语言结构,而不是一个“思考”实体。它应该如何“拾起”?新指针
v
将在每个循环中求值,但
指向已释放的内存区域。当下一个for循环发生时,
(在不通过将它指向向量新位置来修复它的情况下)不知道它已无效,并且将被递增到向量不再存在的下一个无效位置,然后将无效位置与有效的<代码>。()/代码>进行比较,不匹配。注意C++迭代器可能更聪明,并检查该条件。但这会带来额外的成本,C++(如C)的首要目标是尽可能快。验证指针是否有效的开销与语言的性能承诺背道而驰,因此程序员有责任保持它的有效性。(C++不是一种保姆式语言,它给了程序员足够的束缚,让他们可以自食其力。)
int *v = new int[6]{0, 1, 2, 3, 4, 5};
for (size_t i = 0; i < 6; ++i) {
    // do something with `v[i]`
}
delete[] v;
int *v = new int[6]{0, 1, 2, 3, 4, 5};
for (int *it = v; it != v + 6; ++it) {
    // do something with it
}
delete[] v;
int *v = new int[6]{0, 1, 2, 3, 4, 5};
for (int *it = v; it != v + 6; ++it) {
    if (*it == 5 and it + 1 == v + 6) {
       // resize
       {
          int *temp = new int[7]; // allocate new array
          std::copy(v, v + 6, temp); // copy elements
          delete[] v; // delete old array
          v = temp; // reassign pointer
       }
       // Oops! `it` points into `v` that was `delete[]`d above!
    }
}
delete[] v;