这里的向量的行为是什么?

问题描述 投票:0回答:1

我无法理解为什么在下面所示的测试中,迭代器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();
}
stl iterator
1个回答
0
投票

在迭代时插入向量确实是一个坏主意。数据插入可能导致内存重新分配,从而使迭代器无效。在这种情况下,容量不足以插入其他元素,这导致使用不同的地址分配内存。您可以自己检查:

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

该代码编写得很差,您可以使用索引而不是迭代器来使其更健壮。

© www.soinside.com 2019 - 2024. All rights reserved.