我无法理解为什么在下面所示的测试中,迭代器p永远不会到达终点,因此仅当k = 20时循环才会中断? push_back到底在做什么以导致未定义的行为?是因为矢量为我要使用的新元素动态分配了一堆额外的存储空间,并且数量不一定是我将要使用的数量?
#include <iostream>
#include <vector>
#include <list>
using namespace std;
const int MAGIC = 11223344;
void test()
{
bool allValid = true;
int k = 0;
vector<int> v2(5, MAGIC);
k = 0;
for (vector<int>::iterator p = v2.begin(); p != v2.end(); p++, k++)
{
if (k >= 20) // prevent infinite loop
break;
if (*p != MAGIC)
{
cout << "Item# " << k << " is " << *p << ", not " << MAGIC <<"!" << endl;
allValid = false;
}
if (k == 2)
{
for (int i = 0; i < 5; i++)
v2.push_back(MAGIC);
}
}
if (allValid && k == 10)
cout << "Passed test 3" << endl;
else
cout << "Failed test 3" << "\n" << k << endl;
}
int main()
{
test();
}
在迭代时插入向量确实是一个坏主意。数据插入可能导致内存重新分配,从而使迭代器无效。在这种情况下,容量不足以插入其他元素,这导致使用不同的地址分配内存。您可以自己检查:
void test()
{
bool allValid = true;
int k = 0;
vector<int> v2(5, MAGIC);
k = 0;
for (vector<int>::iterator p = v2.begin(); p != v2.end(); p++, k++)
{
cout << v2.capacity() << endl; // Print the vector capacity
if (k >= 20) // prevent infinite loop
break;
if (*p != MAGIC) {
//cout << "Item# " << k << " is " << *p << ", not " << MAGIC <<"!" << endl;
allValid = false;
}
if (k == 2) {
for (int i = 0; i < 5; i++)
v2.push_back(MAGIC);
}
}
if (allValid && k == 10)
cout << "Passed test 3" << endl;
else
cout << "Failed test 3" << "\n" << k << endl;
}
此代码将输出类似以下内容:
5
5
5
10 <-- the capacity has changed
10
... skipped ...
10
10
Failed test 3
20
我们可以看到,在k等于2(第三行)的情况下,向量的容量增加了一倍(第四行),因为我们要添加新的元素。内存已重新分配,向量元素现在很可能位于其他位置。您也可以通过使用data
成员函数而不是capacity
打印矢量基址来检查它:
Address: 0x136dc20 k: 0 Address: 0x136dc20 k: 1 Address: 0x136dc20 k: 2 Address: 0x136e050 k: 3 <-- the address has changed Address: 0x136e050 k: 4 ... skipped ... Address: 0x136e050 k: 19 Address: 0x136e050 k: 20 Failed test 3 20
该代码编写得很差,您可以使用索引而不是迭代器来使其更健壮。