假设您有类似
的类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之前的
答案 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()