为什么指向向量最后一个元素的迭代器持有损坏的值? (参考代码)

Why is the iterator to the last element of the vector holding a corrupted value? (refer code)

下面的代码抛出堆释放后使用错误。

#include <iostream>

int main()
{
    unordered_map<int, vector<int>::iterator> mp;
    vector<int> num;

    auto insert = [&](int n)
    {
        if (mp.count(n) != 0)
            return false;

        num.push_back(n);
        mp[n] = prev(num.end());
        return true;    
    };

    insert(1);
    insert(2);
    insert(3);

    for (auto n : num)
        cout << n << endl;

    cout << endl;

    for (auto m : mp)
    {
        cout << m.first << " -> ";
        cout << distance(num.begin(), m.second) << endl; 
        // cout << *m.second << endl;
    }

    return 0;
}

以上代码的输出为

1
2
3

3 -> 2
1 -> -16
2 -> -7

如果我尝试访问 *m.second,它显然会崩溃。 为什么这里的迭代器值似乎已损坏?

我试过用列表替换向量,上面的代码工作正常。我想知道这是否与 vector 在 "push_back" 上的扩展方式有关。我尝试了其他方法使迭代器指向向量的最后一个元素,但结果无关紧要。

调用 push_back 时,vector 中的迭代器和引用无效,请参阅 reference。 Vector 被实现为一个连续的内存块。当您推送新元素并且没有 space 来保留它们时,将分配新的内存块并添加新的元素。因此指向旧元素的迭代器(指针)可能会失效。

您的代码适用于 std::list,因为列表是使用 nodes 实现的。一个节点指向另一个节点,同时将新数据添加到节点的列表位置不会改变,因此迭代器是有效的。

您使用 vector 的代码可以工作,但您需要估计向量中可以包含多少元素,在创建向量后调用它 reserve(N) - 它准备向量来保存 N 项在调用 push_back 时不会使迭代器无效。