我有一个有效的删除方法,如下:
void deleteUserByID(int id, std::vector<Person*>& userList)
{
for(int i = 0; i < userList.size(); i++) {
if (userList.at(i)->getID() == id) {
userList.erase(userList.begin() + i);
}
}
}
但是,我在上面之前尝试过以下操作,但不明白为什么它不起作用。
而不是使用userList.erase(userList.begin() + i);
,我正在使用delete userList.at(i)
我对 C++ 有点陌生,并被指示使用“delete”关键字删除堆分配的内存。我觉得应该将其从 Vector 中删除,但这是错误的。
为什么不delete userList.at(i)
工作?我很好奇。任何信息都会有帮助。
这里有两个不同的概念在起作用。首先,是对设备的维护std::vector
你正在使用的。向量的工作是保存一系列元素,并且在很多方面它并不真正关心这些元素实际上是什么。从向量的角度来看,它的元素将一直存在,直到有东西明确出现并要求删除它们为止。致电给erase
告诉向量“嘿,你知道那个位置的元素吗?请把它去掉。”因此,当您拨打电话时erase
,你告诉向量去掉它的一个元素。
独立地,有存储在向量中的对象。你正在存储Person *
s,它们是指向Person
对象。这些对象(我假设)被分配了new
,所以每个人本质上都认为“我会永远活着,或者至少直到有人过来打电话delete
在我身上。”如果你delete
Person 对象之一,该对象将不再存在。然而,Person 对象完全不知道某个地方有一个指向人的向量。
为了让一切按照您想要的方式工作,您实际上需要结合使用两者erase
and delete
(有一个警告,我稍后会提到)。如果你只是erase
来自向量的指针,然后从向量的角度来看,所有内容都被清理了(它不再保存指向相关 Person 对象的指针),但从 Person 的角度来看,Person 对象仍然非常活跃并且运行良好,因为你从未说过delete
它。如果你只是delete
指针,然后从人的角度来看,所有东西都被清理了(你已经告诉人,是时候去天空中的巨大游乐场了),但是从矢量的角度来看,没有添加或删除任何内容,所以你现在有一个悬空的向量中的指针。换句话说,第一个选项会导致内存泄漏 - 有一个 Person 对象从未被告知清理自身 - 第二个选项会导致悬空指针 - 有一个指针指向曾经是一个人的对象,但现在是一个人一堆可以按照程序的意愿回收的位。
使用您现在拥有的设置,处理此问题的“最佳”方法是使用组合方法。当您找到要删除的项目时,首先delete
指针,then call erase
。这确保了 Person 被清理并且向量中不再有悬空指针。
但正如一些评论者指出的那样,有更好的方法可以做到这一点。而不是存储Person *
s 并使用原始指针来引用Person
对象,使用std::shared_ptr
输入并管理您的Person
物体通过std::shared_ptr<Person>
。与常规指针不同,常规指针只是说“是的,那边有一个东西”并且不会自行执行任何内存管理,std::shared_ptr
类型实际上拥有它所指向的资源。如果你erase
a std::shared_ptr
从向量中,std::shared_ptr
然后说“好吧,我刚刚被踢出了向量,如果我是指向向量的最后一个指针Person
,我去,delete
为你服务。”这意味着你不需要自己进行任何内存管理来清理事情。
总之:
- 只是打电话
erase
从向量中删除一个元素,但留下一个 Person 在堆中漂流,想知道为什么没有人再喜欢它了。
- 只是打电话
delete
将 Person 对象设置为自由,但会在向量中留下一个指向它的幽灵指针,这是一个主要危险。
- 呼叫两者
delete
and erase
按正确的顺序可以解决此问题,但不是理想的解决方案。
- Using
std::shared_ptr
而不是原始指针可能是最好的选择,因为它确保了所有正确的delete
自动发生。
希望这可以帮助!
还有一个快速附录 - 您确定您的代码正确访问了向量的所有元素吗?例如,如果您erase
索引 0 处的项,向量的所有其他元素将后移一位。但随后你的实施就会增加i
到 1,此时您已跳过刚刚移回第一个位置的项目。
我让你想想如何解决这个问题。另一个答案提供了使用的好建议remove_if
,这是一个很好的解决方案,但如果为了您自己的启发,您想推出自己的版本,您可能需要考虑如何解决上述问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)