繁体   English   中英

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());

或实际分配Level

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();调用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>());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM