c++ - 为什么 .end() 可以返回一个无效的迭代器,而不是每次都被评估(如 .size())并检查它是否仍然有效?
问题描述
我最近了解了 C++ 中的迭代器无效化。我不明白为什么.end()
for 循环中的函数可以返回无效的迭代器,因为它是一个 for 循环,它应该导致.end()
每次循环运行时调用一个函数,就像基于索引的 for 循环会使用.size()
.
引擎盖下是否有某种缓存?是.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;
}
}
如果我it = std::next(v.begin(), v.size() - 2);
在调整大小后不这样做,则迭代器无效。
.size()
索引循环变体不必这样做:
for (size_t i = 0; i < v.size(); ++i) {
if (v.at(i) == 5 and (i+1) == v.size()) {
v.resize(v.size() + 1);
v.at(i + 1) = 999;
v.at(i) = 0;
}
}
更新:感谢您在答案和评论中的解释。这不是.end()
使迭代器无效的函数。整个it
对象都是无效的,我不知何故错过了这样一个事实,即 for 循环中的 begin 语句在auto it = v.begin()
每次迭代之前都没有完成。从逻辑上思考,循环怎么可能工作……
解决方案
基本上是动态分配std::vector<int>
的数组的包装器。int *
那么让我们来看看如何迭代一个数组。
我们可以使用大小进行迭代。您6
的代码中对应于v.size()
:
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;
可以使用指针重写相同的循环。std::vector
与: v.end()
is v = 6
, v.begin()
isv
和std::vector<int>::iterator
is 的相似之处int *
:
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;
因为旧数组被删除,指针it
无效,它指向一块被释放的内存。
推荐阅读
- elasticsearch - 无法启动 ElastAlert:仅支持 pytz 库中的时区
- reactjs - 如何在带有 Deck-GL 层的 Mapbox-GL 静态地图组件中嵌入退出按钮
- c++ - 写入文件和标准输出,std::cout 未显示全部
- performance - 如何使用 FormApp...getResponses() 减少脚本执行时间?
- c# - 尝试使用 'dbcontext.tablename.local' 获取本地列表会引发错误
- handlebars.js - Handlebars - 在带有@root 的条件语句中访问“this”
- asp.net-core - 获取 ASP .NET Core 3.1 / Kestrel 中的连接数
- python - 优化归并排序
- c# - 工作系统,团结 | 包含不同类型的结构的本机数组。错误 InvalidOperationException
- python - 什么是根据另一列中的值填充列的更有效方法