C ++迭代扩展容器
C++ Iterate through an expanding container
如果我在遍历容器的同时扩展容器会发生什么,我会遇到新元素还是旧元素
std::vector<int> arr(0);
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
for (auto& ele : arr) {
if (4 == ele) std::cout << "meet new eles" << endl;
arr.push_back(4);
}
push_back
可能会使向量的任何迭代器无效,你所拥有的是未定义的行为。
std::vector
在内部分配一个数组,其元素连续存储在内存中。为此,它需要预分配它可能需要的大小的估计值,这称为向量的容量。在 push_back
如果达到容量,它会分配一个新的更大的数组, copies/moves 将前一个数组的所有内容分配给新数组,然后删除旧数组。这使迭代器无效,它一直指向已删除的数组。
另外值得一提的是,新数组的分配增加了相当大的性能损失。如果您知道向量的大小,则始终使用 reserve()
来预分配内存。
现在,如果您事先保留容量并且从不推回超过该容量,则迭代器将不会失效(仅尾端迭代器)并且您可以继续递增它们,因为它们指向一个数组的连续元素。但我不建议这样做,IMO 错误地重新分配向量的风险是不值得的。
如果保证永远不会删除元素,最简单的解决方案仍然是使用常规的 for 循环。
for(size_t i=0, n=arr.size(); i<n; ++i)
{
if(/* something */)
{
arr.push_back(/* ... */);
++n;
}
}
我知道这是一个微不足道的解决方案,但其他人可能会搜索并找到这个问题。
来自@Long_GM 的好笔记。这不适用于每个容器。 std::map 例如,无论您是否插入任何值,都无法以这种方式迭代。
如果我在遍历容器的同时扩展容器会发生什么,我会遇到新元素还是旧元素
std::vector<int> arr(0);
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
for (auto& ele : arr) {
if (4 == ele) std::cout << "meet new eles" << endl;
arr.push_back(4);
}
push_back
可能会使向量的任何迭代器无效,你所拥有的是未定义的行为。
std::vector
在内部分配一个数组,其元素连续存储在内存中。为此,它需要预分配它可能需要的大小的估计值,这称为向量的容量。在 push_back
如果达到容量,它会分配一个新的更大的数组, copies/moves 将前一个数组的所有内容分配给新数组,然后删除旧数组。这使迭代器无效,它一直指向已删除的数组。
另外值得一提的是,新数组的分配增加了相当大的性能损失。如果您知道向量的大小,则始终使用 reserve()
来预分配内存。
现在,如果您事先保留容量并且从不推回超过该容量,则迭代器将不会失效(仅尾端迭代器)并且您可以继续递增它们,因为它们指向一个数组的连续元素。但我不建议这样做,IMO 错误地重新分配向量的风险是不值得的。
如果保证永远不会删除元素,最简单的解决方案仍然是使用常规的 for 循环。
for(size_t i=0, n=arr.size(); i<n; ++i)
{
if(/* something */)
{
arr.push_back(/* ... */);
++n;
}
}
我知道这是一个微不足道的解决方案,但其他人可能会搜索并找到这个问题。
来自@Long_GM 的好笔记。这不适用于每个容器。 std::map 例如,无论您是否插入任何值,都无法以这种方式迭代。