c++ - vector 中这种删除方法有什么问题?

标签 c++

我有一种有效的删除方法,如下所示:

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进行维护。 vector 的工作是保存一系列元素,并且在许多方面它实际上并不关心这些元素实际上是什么。从 vector 的角度看,它的元素会一直存在,直到明确出现并说要摆脱它们为止。对erase的调用告诉 vector “嘿,您知道该元素在那个位置上吗?请删除它。”因此,当您调用erase时,就是在告诉该 vector 摆脱其元素之一。

独立地, vector 中存储了对象。您正在存储Person *,它们是Person对象的指针。这些对象(我假设是)被分配了new,因此每个人本质上都认为“我将永远活着,或者至少要等到有人过来叫我delete为止。”如果您对一个Person对象进行delete编码,则该对象将不复存在。但是,Person对象绝对不知道在某处有指向人的 vector 。

为了使所有功能都能按您希望的方式工作,您实际上需要同时使用erasedelete(有一个警告,我将在后面提到)。如果仅对 vector 的指针进行erase编码,则从 vector 的角度来看,所有内容都会被清理(不再保存指向所涉及的Person对象的指针),但是从Person的角度来看,Person对象仍然非常活跃,因为从来没有说过对它进行delete编码。如果只是delete指针,那么从Person的角度来看,所有内容都会被清理(您已经告诉Person,是时候去到空中的巨型操场了),但是从vector的角度来看,什么也没有添加或删除,因此您现在 vector 中有一个悬空指针。换句话说,第一个选项导致内存泄漏-从未告知过要清除其Person对象的Person对象-第二个选项导致了悬空的指针-曾经是一个人的指针,但是现在一堆可以回收的位,但是程序希望如此。

使用您现在拥有的设置,解决此问题的“最佳”方法是使用组合方法。当您找到要删除的项目时,请先对指针进行delete编码,然后调用erase。这样可以确保对Person进行清理,并且确保 vector 中不再具有悬空指针。

但是,正如一些评论者所指出的那样,还有一种更好的方法可以做到这一点。与其存储Person *并使用原始指针引用Person对象,不如使用std::shared_ptr类型并通过Person管理您的std::shared_ptr<Person>对象。与常规指针只说“是的,那边有东西”并且不会自行执行任何内存管理不同,std::shared_ptr类型实际上拥有它指向的资源。如果您用 vector 对erase进行std::shared_ptr编码,则std::shared_ptr会说:“好吧,我刚刚被踢出 vector ,并且如果我是Person的最后一个指针,那么我将为您进行delete编码。”这意味着您不需要做任何自己的内存管理即可清理内容。

总之:

  • 仅仅调用erase会从 vector 中删除一个元素,但是却使Person漂泊在堆中,想知道为什么没人再爱它了。
  • 只需调用delete即可释放Person对象,但会在 vector 中留下指向它的幽灵指针,这是一个重大危害。
  • 以适当的顺序调用deleteerase可以解决此问题,但这不是理想的解决方案。
  • 使用std::shared_ptr代替原始指针可能是最好的选择,因为它可以确保所有正确的delete都自动发生。

  • 希望这可以帮助!

    快速附录-您确定代码正确访问了 vector 的所有元素吗?例如,如果您对索引为0的项目进行erase,则 vector 的所有其他元素将向后移一个位置。但是然后您的实现将i递增为1,这时您跳过了刚刚移回到第一位置的项目。

    我会让您考虑如何解决此问题。另一个答案为使用remove_if提供了一个很好的建议,这是一个很好的解决方案,但是如果您出于自己的兴趣,想要推出自己的版本,则可能需要考虑如何解决上述问题。

    关于c++ - vector 中这种删除方法有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51583374/

    相关文章:

    c++ - 从 jpeg 内存缓冲区创建 HBITMAP?

    c++ - C处理局部变量

    c++ - 如何在 Win32 应用程序中拖动纯色矩形而不会出现白色闪烁且不会干扰屏幕上的其他对象?

    c++ - 在二维 std::vector 中设置元素

    c++ - 如何隔离两个同名的C++类?

    c++ - 使用 volatile 标准模板对象的方法

    c++ - 无继承多态性

    c++ - 稳定红外距离传感器输出值

    c++ - 为什么不调用继承自 QSortFilterProxyModel 的 filterAcceptsRow?

    c++ - 使用自定义比较功能使用std::sort()对 vector 字符串进行排序时遇到问题