在c++中删除STL映射中的分配内存

Delete allocated memory in a STL map in C++

本文关键字:分配 映射 内存 STL c++ 删除      更新时间:2023-10-16

我使用映射来存储一对(int和class),使用如下:

#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用户定义的次数,所以可以删除每个数据库条目的方法是首选,谢谢!

如果有办法,我可以做到这一点,而不使用内存分配,这也将是有用的

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

通常解决这个问题的方法是使用智能指针,例如:std::unique_ptrstd::shared_ptr(都是c++ 11,对于c++ 03 永远不要在容器中使用 std::auto_ptr,因为它是坏的,但你可以安全地使用boost智能指针代替)。

所以你的map类型会变成eg。std::map<int, std::unique_ptr<abstractclass>>。那么你就不需要再为删除对象而烦恼了,当它们从映射中删除时,智能指针会自动处理它。

另一个解决方案是自己delete所有项目(如@MarkB所说),但这是非常容易出错的,所以智能指针通常在可能的情况下首选

只要您的abstractclass具有虚析构函数,您就可以简单地遍历容器中的所有项,并在delete中迭代该项的second组件以释放内存。有多种方法可以做到这一点:例如For循环,或for_each与函子或lambda。

编辑:经过进一步的审查,地图似乎有所有权,如果你使用shared_ptrmap(来自boost或c++ 11),或者使用boost::ptr_map,你的生活会更轻松。然后你就不用担心清理地图了——你可以使用db.clear();,所有的物品都会自动清理。这两种容器都有助于在插入重复项时管理内存。

你可以在你的容器中使用智能指针:

#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. 你可以插入一个空指针,然后用一个实际创建的值重置它(即不创建一个对象,如果这个键的值已经存在)