无法解释为什么指针在创建指针向量矢量时会变得悬空

时间:2017-03-26 04:27:25

标签: c++ pointers dangling-pointer

请考虑以下代码:

#include <iostream>
#include <vector>

using namespace std;

class SomeClass {
public:
    SomeClass(int num) : val_(num) {}
    int val_;
    int val() const { return val_; }
};

// Given a vector of vector of numbers, this class will generate a vector of vector of pointers
// that point to SomeClass.
class Generator {
public:
    vector<SomeClass> objects_;
    vector<vector<SomeClass*> > Generate(const vector<vector<int> >& input) {
        vector<vector<SomeClass*> > out;
        for (const auto& vec : input) {
            out.push_back({});
            for (const int num : vec) {
                SomeClass s(num);
                objects_.push_back(s);
                out.back().push_back(&objects_.back());
            }
        }
        return out;
    }
};

int main() {
    Generator generator;
    auto output = generator.Generate({{2, 3}, {4, 5}, {6}});
    for (const auto& vec : output) {
        for (const auto* obj : vec) {
            printf("%d ",obj->val());
        }
        printf("\n");
    }
    return 0;
}

Generate类中的Generator方法只会将int s的向量向量转换为指向SomeClass的向量向量。

SomeClass只是一个带有getter方法的简单int值的容器。

我希望得到以下结果:

2 3
4 5
6

但是,我得到以下输出:

junk_integer junk_integer
4 5
6

似乎第一行中的指针变成了悬空指针。这段代码有什么问题?

3 个答案:

答案 0 :(得分:1)

您将指针存储到vector,然后向向量添加元素。由于您没有为所有要添加的元素保留足够的空间,因此当向量调整大小时,它会使指向旧数据的所有指针无效。

你需要在存储指针之前保留足够的空间,在你需要存储的向量中存储所有内容之后存储指针,或者不存储指针(可能存储索引)

答案 1 :(得分:1)

如果调整大小导致向量更改,那么增加std::vector中元素数量的所有操作(包括push_back())都会使引用元素元素的所有迭代器(包括指针)无效容量。

您的代码正在执行

objects_.push_back(s);
out.back().push_back(&objects_.back());
循环中的

objects_.push_back()的每次调用都会使objects_的迭代器无效,因此会导致out.back()包含无效(悬空)指针。

答案 2 :(得分:0)

您正在存储指向generator.objects_中包含的对象的指针。当你打电话给push_back()时,其中一些会成为悬空指针。

通常,将指针存储到std::vector中的对象是一个坏主意。