C++ 初始化程序不断地在同一内存位置创建新对象

C++ initializer constantly creating new objects at same memory location

我有一个简单的递归类型容器对象"Level"(比如一个目录,它可以包含多个自身),虽然我不确定这是否与这个问题有关。

//Level.h
class Level
{

public:

    Level();
    vector<Level*> SubLevels;
    Level CreateSubLevel();
}

//Level.cpp
Level::Level()
{
    SubLevels = vector<Level*>();
}

Level Level::CreateSubLevel()
{
    Level NewLevel = Level();

    SubLevels.push_back(&NewLevel);

    return NewLevel;
}

如果然后在我的主循环中调用

//main.cpp
Level MasterLevel = Level();
MasterLevel.CreateSubLevel();
MasterLevel.CreateSubLevel();
MasterLevel.CreateSubLevel();

我发现向量 MasterLevel.SubLevels 确实包含三个指向 Level 对象的指针。但是,它们都是指向同一个地址的指针!

我不确定为什么会这样。我缺乏内存管理技能 - 但我怀疑这是因为每次调用 CreateSubLevel() 时都会创建一个新对象,但当 CreateSubLevel() 退出时它会被删除?我以为 ARC 会跟踪指向它的指针仍然存在的事实,但也许我错了?或者这完全是另一个问题?

我怎样才能最好地解决这个问题?

谢谢!

SubLevels 持有三个指向临时对象的指针。编译器选择每次都为临时对象重用相同的内存并不奇怪——为什么不呢?

如果您想实际正确存储三个不同的 Level,您要么必须按值存储它们:

vector<Level> SubLevels;
SubLevels.push_back(Level());

或者实际分配Levels:

vector<Level*> SubLevels;
SubLevels.push_back(new Level); // don't forget to delete!

你每次得出相同值的原因是因为你使用的是临时变量(在堆栈上)的地址。每次调用函数 CreateSubLevel() 时,都会重复使用堆栈,因此每次调用时对象都存储在相同的位置。

您可以使用 operator new():

在堆上分配对象
vector<Level*> SubLevels;
SubLevels.push_back(new Level);

然后你可以在析构函数中delete它们:

Level::~Level()
{
    vector<Level*>::iterator i;
    for (i = SubLevels.begin(); i != SubLevels.end(); ++i)
        delete *i;
}

您接连打了三个 MasterLevel.CreateSubLevel(); 电话。每次调用都会创建一个大小相同的堆栈帧。因此,局部变量的地址是相同的。您将局部变量的地址存储在 SubLevels.

如果你使用存储在SubLevels中的地址,你会运行进入未定义的行为。您需要从堆中分配内存。

当你这样做的时候,保留一个智能指针列表,std::unique_ptrstd::shared_ptr 而不是存储原始指针。

使用

vector<std::shared_ptr<Level>> SubLevels;

并将其用作:

void Level::CreateSubLevel()
{
    SubLevels.push_back(std::make_shared<Level>());
}