0

我想知道,如果我在 main 中使用 new 关键字创建一个对象,然后将该对象(指针)设置为由另一个类的成员指向,将原始指针设置为 null,我将在哪里删除分配的内存?我可以在第二个类的析构函数中做到这一点,但如果该对象不是动态分配的呢?

一些代码作为例子:

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

所以现在 World 中的 'player' 成员变量指向 newPlayer 分配的内存,而 newPlayer 指向 null。使用完 World 对象后,我应该如何释放此内存?

4

5 回答 5

6

这种复杂性是您应该尽量避免在 C++ 中使用原始指针的原因。 存在智能指针来解决此类问题,并省去手动跟踪谁拥有对象以及何时删除它的麻烦。

例如:

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!
于 2012-07-12T10:22:35.700 回答
3

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

如果所有玩家都传递给 aWorld然后World可以处理内存 - 每次 aWorld被破坏或设置不同的玩家时PlayerWorld必须删除持有的。此外,任何玩家都不应该在其他任何地方被摧毁,否则它可能会被摧毁两次。但是在这种情况下,我会让所有 Players 都由一个方法构造,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 对象,因此删除原始世界和副本不会尝试删除同一个 Player)

于 2012-07-12T10:26:30.170 回答
1

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

例如,从您的对象的名称来看,我猜它world拥有一切;它决定了玩家的寿命等。在这种情况下,它应该负责delete。至于Person在堆栈上分配 a 的可能性:不要那样做。鉴于它 Person可能有一个明确的生命周期,它与函数中的块对应(否则,为什么要动态分配它开始),声明该类型的局部变量是没有意义的。

于 2012-07-12T10:39:06.910 回答
0

完成后只需要调用 delete 即可。为了避免这样做的需要,请考虑使用共享指针,因为它们将使您不再需要这样做。

编辑:要回答您的评论,您拨打的电话delete取决于您的应用程序,但请确保您

  1. delete在分配之前不要这样做。
  2. delete在您确定没有其他东西需要访问它之前不要这样做。

一个可能的位置是在 World 对象的析构函数中,但如果不知道应用程序其余部分的详细信息,就不可能说出来。这就是为什么boost::shared_ptr更可取。

于 2012-07-12T10:22:54.217 回答
-1

新的应该总是跟在删除之后。如果将指针设置为指向其他对象而不释放内存,则会导致指针悬空

于 2012-07-12T10:21:25.417 回答