【问题标题】:What is the behavior of the vector here?向量在这里的行为是什么?
【发布时间】:2020-06-01 00:58:34
【问题描述】:

我无法理解为什么在下面显示的测试中,迭代器 p 永远不会到达末尾,因此循环仅在 k = 20 时才中断? push_back 究竟是在做什么来导致未定义的行为?是不是因为vector为我要使用的新元素动态分配了一堆额外的存储空间,而数量不一定是我要使用的数量?

#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】:

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

    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
    

    代码写得不好,你可以通过使用索引而不是迭代器来使其更健壮。

    【讨论】:

      猜你喜欢
      • 2023-02-13
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2011-07-29
      • 2018-06-29
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多