删除类对象是否会删除所有成员向量的对象?

时间:2017-10-27 14:33:29

标签: c++

假设您有类似

的类
class Manager {
   public:
     vector<Player> players;
     void AddSoManyPlayers();
}

void Manager::AddSoManyPlayers(){
   Player* player1 = new Player();
   Player* player2 = new Player();
   Player* player3 = new Player();
   Player* player4 = new Player();
   players.push_back(*player1);
   players.push_back(*player2);
   players.push_back(*player3);
   players.push_back(*player4);
}

然后,您将Manager对象添加到Player向量后删除players或超出范围。

int main(){
  Manager manager;
  manager.AddSoManyPlayers();
  return 0;
}

Player中的每个players都会调用他们的解构函数吗?我发现当试图从~Manager()通过players.clear()清除向量时,编译器说我试图释放两次内存,所以我想我知道答案。但是从我读过的内容来看,这是非常意外的 - 即必须始终删除每个新的

延迟注意:我是C + 11之前的

2 个答案:

答案 0 :(得分:2)

  

删除类对象是否会删除其所有向量对象?

是。超级对象被销毁时,所有子对象都将被销毁。

  

玩家中的每个玩家都会得到他们的解构者吗?

是。当容器被销毁时,容器的所有元素都被销毁。

但是,playerX指向的动态对象永远不会被删除,当这些本地指针超出Manager::AddSoManyPlayers末尾的范围时,就再也无法删除它们了。

  

那么为什么,如果我遍历向量并明确删除每个Player,编译器会抱怨内存损坏/双重删除吗?我应该在哪里删除每个Player

正如我所说,当容器被摧毁时,矢量中的玩家将被摧毁。你不应该明确地删除它们。

  

但是我所读到的内容非常出乎意料 - 即每个新内容都必须删除。

这不是唯一要记住的经验法则。另一个规则是要删除的指针必须是new返回的指针。您不会将这些指针存储在向量中,因此您不会从向量中删除任何内容。您将指针存储在playerX变量中,因此必须删除这些变量。

更好:首先不要创建动态对象。这就是如何在不创建动态向量的情况下在向量中创建新玩家的方法:

players.emplace_back();

这就是你可以创建所有4合一呼叫的方法:

players.resize(4 + players.size());
  

我认为宣称不是新的东西将会超出范围,在这种情况下AddSoManyPlayers

事实上。这就是playerX指针在AddSoManyPlayers末尾被销毁的原因,此时它们指向的动态对象不再被删除。

  

一旦AddSoManyPlayers方法完成(超出范围),Player对象将如何生存

vector<Player> players未在AddSoManyPlayers的范围内声明,因此它不会在它的末尾被销毁,因此它的元素也不会被销毁,因此将在返回时存活。

似乎你还没有解决这个问题,这可能是混淆的根源:向量中的对象与push_back的参数给出的对象不同。向量中的对象是该参数的副本。

答案 1 :(得分:1)

  

玩家中的每个玩家都会得到他们的解构者吗?

是的。您的代码中有不同的问题,您可以通过operator new动态分配4个对象,将它们的副本放入std::vector然后让它们泄漏。如果您明确地或std::vector的析构函数调用clear(),则std::vector中的那些副本将被销毁,但原件不会被销毁。您需要手动销毁它们或使用智能指针而不是原始指针:

void Manager::AddSoManyPlayers(){
   Player* player1 = new Player();
   Player* player2 = new Player();
   Player* player3 = new Player();
   Player* player4 = new Player();
   players.push_back(*player1);
   players.push_back(*player2);
   players.push_back(*player3);
   players.push_back(*player4);
   delete player4;
   delete player3;
   delete player2;
   delete player1;
}

但不清楚为什么需要动态分配原件。

如果您打算动态分配对象并让Manager维持其生命周期,那么请使用智能指针:

class Manager {
   public:
     std::vector<std::unique_ptr<Player>> players;
     void AddSoManyPlayers() {
         players.emplace_back( new Player );
         ...
     }
}

然后你不会将副本放入向量中,并且你的对象会被析构函数正确删除(你不需要明确地调用std::vector::clear()