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

时间:2015-09-04 00:37:24

标签: c++ pointers automatic-ref-counting

我有一个简单的递归型容器对象" 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会记录指向它的指针仍然存在的事实,但也许我错了?还是完全是另一个问题?

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

谢谢!

3 个答案:

答案 0 :(得分:2)

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

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

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

或实际分配Level s:

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

答案 1 :(得分:1)

每次出现相同值的原因是因为您正在使用临时变量的地址(在堆栈上)。每次调用函数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;
}

答案 2 :(得分:1)

您可以一个接一个地拨打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>());
}