![](/img/trans.png)
[英]Having trouble in C++ Creating vector of pointers or map of Pointer values
[英]Having trouble deleting vector of pointers
我有一个管理器类,它包含一个指向虚拟基类的指针向量,允许在那里存储各种子类。 在这个管理器类的析构函数中,我希望它循环遍历它所拥有的所有指针并删除它们。 但是,我尝试了许多方法,程序在执行过程中不断崩溃。
我现有的代码如下所示: -
for (std::vector<GameState*>::iterator it = gamestates_.begin(); it != gamestates_.end(); ++it){
delete *it;
it = gamestates_.erase(it);
}
我还没有尝试过的一件事是使用unique_ptr,但我确信这应该能够在不使用它们的情况下处理它。 如果我错了,请纠正我。
编辑:我知道我应该在循环之后清除向量,但这是我在尝试删除指针的每个常规方法后所得到的。 它似乎不喜欢删除命令。
从向量中删除元素会使迭代器无效,因此您无法继续迭代。 在这种情况下,我不会擦除循环中的元素; 之后我会清除矢量:
for (auto it = gamestates_.begin(); it != gamestates_.end(); ++it){
delete *it;
}
gamestates_.clear();
虽然,如果这是在析构函数中并且矢量即将被销毁,那么也没有必要清除它。
如果你确实需要在循环中擦除(也许是因为你只想删除一些元素),那么你需要更加小心以保持迭代器有效:
for (auto it = gamestates_.begin(); it != gamestates_.end();){ // No ++ here
if (should_erase(it)) {
it = gamestates_.erase(it);
} else {
++it;
}
}
我还没有尝试过的一件事是使用
unique_ptr
但我确信这应该能够在不使用它们的情况下处理它。 如果我错了,请纠正我。
如果你确实希望通过蒸汽管理动态对象,那么请确保遵循规则三 :你需要实现(或删除)复制构造函数和复制赋值运算符,以防止“浅”复制离开你两个试图删除相同对象的向量。 您还需要注意删除删除或替换它们的任何其他位置的对象。 存储智能指针(或者对象本身,如果你不需要多态性的指针)将为你处理所有这些事情,所以我总是建议这样做。
我知道我应该在循环之后清除向量,但这是我在尝试删除指针的每个常规方法之后所得到的。 它似乎不喜欢删除命令。
最可能的原因是您没有遵循三规则,并且在复制矢量后意外地尝试删除两次相同的对象。 GameState
也可能是一个基类,你忘了给它一个虚拟析构函数,或者指针已经被其他代码破坏了。
您的迭代器在每个循环中更新两次:
it = gamestates_.erase(it);
和
it++
你只需要第一个 - 它已经指向容器中的“下一个对象”。
从向量中删除元素会使迭代器无效。 按元素删除对象指针,然后clear()
向量的内容。
摆脱你的for
循环标题中的++it
。
erase
已经为你进步了。
或者,迭代,删除,然后迭代.clear()
。
更喜欢使用unique_ptr
。 你说你应该能够在不使用它们的情况下处理它 ,好像获得一个智能指针为你做的工作是某种可怕的强加。
他们在那里让你的生活更轻松,你不必因为不用手工做而感到内疚。
使用现有代码,只需不要调用erase
。 无论如何,矢量将被摧毁,对吧? 它会照顾好自己。
问题是,你正在增加it
的两倍。 首先,当你调用it = .erase(it)
返回下一个元素,然后在循环++i
。 你可能无意中跳过了最后,事情可能会出错,更不用说你只会删除你向量的每一个元素。
一个简单的解决方法就是不要在循环中改变it
(没有++it
)。
更好的方法是从向量的末尾实际删除数组,因为向量内部的擦除元素引入了所有后续元素的昂贵移动。 您当前的算法将在N^2
时间内工作。 尝试这样的事情:
while (!gamestates_.empty()) {
delete gamestates_.back();
gamestates_.erase(gamestates_.end()-1);
}
您也可以迭代向量的所有元素并在之后清除它:
for (std::vector<GameState*>::iterator it = gamestates_.begin(); it != gamestates_.end(); ++it){
delete *it;
}
gamestates_.clear();
另请注意,向量的clear()
操作也在其析构函数中完成。 如果删除过程是某些销毁过程的一部分,其中gamestates_
被极度破坏 - 您根本不必调用clear()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.