在C++的STL(标准模板库)中,如何删除分配的内存?(针对map容器)

3
我正在使用一个地图来存储一个键值对(int和class),方法如下: ``` map myMap; ```
#include <iostream>
#include <utility>
#include <map>
using namespace std;

class abstractclass{...};

class derivedclass : public abstractclass{...};

typedef map<int,abstractclass*> dBase;

int main(){
    dBase db;
    db.insert(pair<int,abstractclass*>(123,new derivedclass));
    db.insert(pair<int,abstractclass*>(124,new derivedclass));
}

如何释放已分配的内存?

我需要能够使用insert方法来插入用户定义的次数,因此最好有一种可以删除每个数据库条目的方法,谢谢!

如果有一种不使用内存分配的方法也很有用。

3个回答

11

由于你的类层次结构,显然不能直接按值存储abstractclass对象于map中,否则会遇到臭名昭著的对象切割问题

解决这个问题的通常方法是使用智能指针,例如std::unique_ptrstd::shared_ptr(两者均为C++11,对于C++03,不要在容器中使用std::auto_ptr,因为它已经被弃用,但可以安全地使用boost智能指针代替)。

因此,你的map类型将成为例如std::map<int, std::unique_ptr<abstractclass>>。 当从地图中删除对象时,智能指针将自动处理删除对象的操作。

另一种解决方案是自己delete所有项目(如@MarkB所说),但这非常容易出错,因此在可能的情况下通常优先考虑使用智能指针。


4
只要您的abstractclass有一个虚析构函数,您就可以简单地遍历容器中的所有项,并删除项目的second组件以释放内存。有多种方法可以做到这一点:例如使用for循环,或者使用一个函数对象或lambda的for_each
编辑: 经过进一步审查,似乎在这里map具有所有权,如果您使用boost或C++11的shared_ptrmap,或者使用boost::ptr_map,那么您的生活将变得更加轻松。然后,您就不必担心清理映射 - 您只需使用db.clear();,所有项目都将自动清除。这些容器中的任何一个都将有助于在插入重复项时管理内存。

这样行吗: for(dbIT = db.begin(); dbIT != db.end();++dbIT){ delete dbIT->second; } 其中 dbIT 是 dBase::iterator dbIT - Eduardo
在插入调用时,有没有一种简洁的方法来删除重复条目? - spiritwolfform
@10WaRRioR01:不,你必须自己处理这个问题,否则很容易变成一个头疼的问题(insert 可能会抛出异常,因此你需要编写异常安全的代码,只有在插入失败时才会删除你 new 的对象,可以使用智能指针或 try/catch,这会使代码变得更加复杂)。 - syam
@clairharrison:是的,这就是想法。然而,避免内存泄漏不仅仅是在程序结束时删除地图中的对象,还有很多其他需要注意的地方,你需要非常小心处理。 - syam
除非对象确实具有共享所有权,否则我更喜欢使用std::unique_ptr而不是std::shared_ptr。 - Adrian McCarthy

3
你可以在你的容器中使用智能指针:
#include <iostream>
#include <utility>
#include <map>
#include <memory>
using namespace std;

class abstractclass{...};

class derivedclass : public abstractclass{...};

typedef map<int,shared_ptr<abstractclass>> dBase;

int main(){
    dBase db;
    shared_ptr<abstractclass> ptr1(new derivedclass);
    shared_ptr<abstractclass> ptr2(new derivedclass);
    db.insert(pair<int,shared_ptr<abstractclass>>(123,ptr1));
    db.insert(pair<int,shared_ptr<abstractclass>>(124,ptr2));
}

共享指针会带来一些额外的开销,但它们的优点是:
  1. 您不必担心删除对象 - 它们将在地图被销毁时被删除。
  2. 您可以安全地创建一个新对象并尝试将其插入地图 - 如果插入失败(即使是异常),分配的对象也将被安全地销毁。
  3. 您可以插入一个空指针,并稍后使用reset()函数将其重置为实际创建的值(即如果已存在具有该键的值,则不实际创建对象)。

谢谢,我将来会用到这个方法。不过,我需要证明我知道如何删除为这个项目分配的内存,但是你的方法在长期使用中会更有用。 - Eduardo
如果你向检查你项目的人解释你如何以及为什么使用智能指针,那会给你更多的加分。 - DarkWanderer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接