前言
本系列旨在总结归纳博主那些年写过bug,如有不正确的地方,还请指正。
本文测试环境
| 编程语言 | 操作系统 | 系统架构 | IDE |
|---|---|---|---|
| C++ 11 | Windows 10 | x64 | Visual Studio 2013 |
一、容器扩容
1.1错误代码举例
先给出错误代码,大家可以先试着自己理解、思考下原因。
std::vector<int> vValue;
for (int i = 0; i<10; ++i)
{
vValue.push_back(i);
std::cout << i << ": " << vValue.at(i) << std::endl;
}
int nPos = 0;
int nNum = 100;
for (std::vector<int>::iterator ite = vValue.begin(); ite != vValue.end(); ++ite)
{
++nPos;
if (nNum != *ite)
{
vValue.push_back(nNum); //! 这里会出错
}
std::cout << nNum << ": " << vValue.at(nNum - 100) << std::endl;
++nNum;
if (120 < nNum)
{
break;
}
}

1.2原因分析
由于std::vector在内存中是连续的,当插入新元素(即容器扩容)时,会造成分配的连续内存不够用了,此时std::vector会开辟一块儿新的空间,然后再将原来的数据拷贝到新的空间,最后释放旧空间。
综上,std::vector扩容后,会导致原先迭代器ite指向的位置(或者说地址?)发生变化,即指向原先位置的迭代器统统失效。
1.3解决办法
既然根本原因是指向原先位置的迭代器失效,那让迭代器指向新的位置,问题不就迎刃而解了吗。
修改后的代码如下:
std::vector<int> vValue;
for (int i = 0; i<10; ++i)
{
vValue.push_back(i);
std::cout << i << ": " << vValue.at(i) << std::endl;
}
int nPos = 0;
int nNum = 100;
for (std::vector<int>::iterator ite = vValue.begin(); ite != vValue.end(); ++ite)
{
++nPos;
if (nNum != *ite)
{
vValue.push_back(nNum); //! 这里会出错
// 重新指定迭代器指向的位置,避免迭代器因容器扩容而失效
ite = vValue.begin();
ite = std::next(ite, nPos);
}
std::cout << nNum << ": " << vValue.at(nNum - 100) << std::endl;
++nNum;
if (120 < nNum)
{
break;
}
}

注: 以上只是为了说明迭代器无效问题而写的测试Demo,实际项目中,不能在以容器大小范围的循环中插入元素,否则会导致无法退出 for()循环
二、To be continued
在查阅资料时,发现导致迭代器失效,还有其他情况,以后碰到再说(或者有空了补上)…

422

被折叠的 条评论
为什么被折叠?



