我有两个代码示例,它们完全相同。一个是C ++ 03和C ++ 11。
C ++ 11
int main()
{
vector<int> v = {1,2,3};
int count = 0;
for each (auto it in v)
{
cout << it<<endl;
if (count == 0)
{
count++;
v.push_back(4);//adding value to vector
}
}
return 0;
}
C ++ 03
int main()
{
vector<int> v = {1,2,3};
int count = 0;
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it<<endl;
if (count == 0)
{
count++;
v.push_back(4);//adding value to vector
}
}
return 0;
}
这两个代码都给出了以下异常。
现在,当我看到vector :: end()实现时,
iterator end() _NOEXCEPT
{
// return iterator for end of mutable sequence
return (iterator(this->_Mylast, this));
}
这里,内联函数显然需要_Mylast
来计算结束。因此,当我添加时,它的指针将递增到下一个位置,如_Mylast++
。为什么我得到这个例外?
感谢。
答案 0 :(得分:10)
向量将其元素存储在连续的内存中。如果需要重新分配该内存块,则迭代器将变为无效。
如果您需要在迭代时修改向量的大小,请按索引而不是iterator
进行迭代。
另一种选择是使用具有不同迭代器行为的不同容器,例如list
将允许您在插入项目时继续迭代。
最后,(我敢建议吗?)如果你知道你的向量将增长到的最大大小,.reserve()
之前迭代它。这将确保它在循环期间不会重新分配。我不确定这种行为是否由标准保证(也许有人可以插入);我绝对不会这样做,考虑通过索引迭代是完全安全的。
答案 1 :(得分:4)
您的push_back
使您在for
循环中使用的迭代器无效,因为该向量正在重新分配其内存,这会使所有迭代器无效到向量的元素。
惯用解决方案是使用insert_iterator
,就像在向量上调用std::back_insterter
时得到的那样。然后你可以这样做:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v;
auto inserter = std::back_inserter(v);
for(int i=0; i<100; ++i)
inserter = i;
for(const auto item : v)
std::cout << item << '\n';
}
即使通过底层容器的重新分配调用,它也能确保自己的有效性。