C ++ - 释放在main中分配但在单独的类中指向的内存

时间:2012-07-12 10:20:00

标签: c++ memory-management

我想知道,如果我使用new关键字在main中创建一个对象,那么将该对象(指针)设置为由另一个类的成员指向,将原始指针设置为null,我将在哪里删除已分配的记忆?我可以在第二个类的析构函数中执行此操作,但如果该对象未动态分配会怎样?

以某些代码为例:

World world;
Player* newPlayer = new Player("Ted");
world.setPlayer(newPlayer);
newPlayer = 0;

所以现在World中的'player'成员变量指向newPlayer分配的内存,newPlayer指向null。当我完成World对象时,我应该如何解除分配这段记忆?

5 个答案:

答案 0 :(得分:6)

这种复杂性是你应该尝试避免使用C ++中的原始指针的原因。 Smart pointers可以解决这类问题,让您省去手动跟踪谁拥有对象所有权以及何时删除它的麻烦。

例如:

typedef boost::shared_ptr<Player> sp_Player;

struct World {
    sp_Player player;
    World(sp_Player p) : player(p) {}
};


sp_Player newPlayer = new Player("Ted");

World world;
world.setPlayer(newPlayer);

// Object is now automatically deleted at the correct time!

答案 1 :(得分:3)

如其他答案中所述,使用智能指针更容易,但在这种情况下,您可以将删除放在其他位置。

如果所有玩家都被传递到World,则World可以处理内存 - 每次World被破坏或者设置不同的玩家时Player必须删除World持有的{}。也不应该在任何其他地方销毁播放器,否则它可能被销毁两次。但是在这种情况下,我会通过World中的方法构建所有玩家,以便清楚谁拥有内存管理并保持同一个类创建和销毁Player对象

一些非常不完整的代码是(注意智能指针代码如何更少,我认为涵盖所有情况 - 这不是)

class World
{
   Player *p;
 ...
}

World() : p(nullptr) {
  ...
}

~World() {
    delete p;
}

void World setPlayer( Palyer *aP ) {
    if ( p != aP) {
         delete p;
    }
    p = aP;
    ....
}

Player* World::createPlayer(std::string const& name){ 
  return new Player(name); 
} 

注意= Player(name)在堆栈上创建一个Playeobject,并且不会通过new和delete在您的代码中进行管理 - 这可能是最好的解决方案。

还需要处理operator =和复制构造函数(后者最好阻止它被调用,或者它需要复制Player对象,因此删除原始世界并且副本不会同时尝试删除它播放器)

答案 2 :(得分:1)

没有绝对的答案。问题是:你为什么要分配 动态开始的对象?一旦你回答了这个,那就是 通常很明显应该删除的地方。

例如,根据对象的名称,我猜是world拥有的 一切;它决定了球员的一生等等 它应该对delete负责。至于可能性 在堆栈上分配Person:不要这样做。鉴于 Person可能有一个对应的绝对生命周期 到函数中的块(否则,为什么动态分配它) 以)开头,声明局部变量是没有意义的 类型。

答案 3 :(得分:0)

完成后你只需要调用delete。尽管需要考虑使用共享指针,但是为了避免这种需要,因为它们可以减轻你的需要。

修改:要回答您的评论,您致电delete的地方取决于您的申请,但请确保

  1. 在分配之前不要delete
  2. 不要delete它,直到你确定没有其他东西需要访问它。
  3. 可能的地方是你的World对象的析构函数,但是如果不知道你的应用程序其余部分的详细信息,就不可能说出来。这就是boost::shared_ptr更可取的原因。

答案 4 :(得分:-1)

new应始终随后删除。如果将指针设置为指向某个其他对象而不释放内存,则会导致dangling pointer