C++:矢量<Foo*> 带 reserve()、push_back() 破坏值

C++: vector<Foo*> with reserve(), push_back() destroying values

本文关键字:push back lt 矢量 Foo C++ gt reserve      更新时间:2023-10-16

标题有点令人困惑。这是我目前困境的一个大大压缩的版本:

类.h:

class Foo {
    int x;
    Foo(): x(0) { }
    Foo(int y): x(y) { }
};
class B {
    vector<Foo> list;
    B() { }
};
class A {
    vector<B> map;
    A() { }
};

主.cpp:

vector<A> map;
vector<Foo*> allFoos;
void initialize() {
    allFoos.reserve(...);
}
void generateMap() {
    for (...) {
        A a;
        map.push_back(a);
        for (...) {
            B b;
            map.back().map.push_back(b);
            if (...) {
                switch (...) {
                case ...:
                    Foo foo(5);
                    map.back().map.back().list.push_back(foo);
                    allFoos.push_back(&map.back().map.back().list.back());
                    cout << allFoos.back()->x; // #1
                    break;
                }
                cout << allFoos.back()->x; // #2
            }
            cout << allFoos.back()->x; // #3
        }
        cout << allFoos.back()->x; // #4
    }
    cout << allFoos.back()->x; // #5
}
int main() {
    initialize();
    generateMap();
}

当我运行我的代码时,我完全能够检索allFoos.back();我可以通过 -> 访问成员,并且在使用 Break 时,使用 MVC++ Express 2013,我可以将鼠标悬停在allFoos上并获得其所有元素的列表......问题是,除了back()元素之外的任何元素都是完全无稽之谈

偶尔,成员价值观变得荒谬;在 #1、#2、#4 和 #5 处,它将打印"5"。在#3处,它将打印一个乱码数字+-几百万。*

经过大量的休息、变量的转储等,我确定问题是push_back(...)以某种方式改变了前面指针的位置,尽管reserve(...)分配了足够的空间来容纳我需要的尽可能多的Foo*

我完全迷失了。我已经尝试了几个小时来理解为什么会发生这种情况,但无济于事。我已经看过数百个类似的问题,但没有一个足够接近来帮助我的问题(除非我没有足够的能力将他们的解决方案应用于我自己的问题。

如果需要更多信息,可以提供。

更新:

更奇怪的是:如果我在 Foo 类中创建一个 printDetails() 成员函数并将其用于 #5 处的allFoos.back(),则所有 Foo 的成员值打印都很好 - 并且相同的悬停技术表明最后一个Foo*是唯一一个细节完好无损的函数。*

更新#2:

*我发现我所说的一切都会根据运行而变化 - 每次,不同的位置打印不同的值,并且我无法确定提供一致结果的位置。似乎我在某处遇到了未定义的行为,但我似乎找不到在哪里......

你的指针是无效的,因为当你在向量中推送值时,一些值最终会被扩展。由于向量连续存储数据,因此在重新分配时,现有值将移动到内存中的另一个位置。因此,原始指针指向以前的无效位置。

如果要继续像示例中那样填充向量,则应事先为所有向量保留适当的大小。但请记住,保留指向矢量元素的原始指针最终会再次引发相同的问题。