3

我正在使用地图来存储一对(int和类),使用以下内容:

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

如果有一种方法我可以在不使用内存分配的情况下做到这一点,那也很有用

4

3 回答 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 所说),但这很容易出错,因此通常在可能的情况下首选智能指针。

于 2013-05-06T14:10:33.207 回答
4

只要您abstractclass有一个虚拟析构函数,您就可以简单地遍历容器中的所有项目和项目deletesecond组件以释放内存。有多种方法可以做到这一点:例如 for 循环,或者for_each使用仿函数或 lambda。

编辑:经过进一步审查,地图似乎在这里拥有所有权,如果您使用 a of (来自 boost 或 C++11),或者使用 a代替,您的生活会容易得多。然后你完全不用担心清理地图——你可以使用,所有的项目都会被自动清理。这些容器中的任何一个也有助于在插入重复项时管理内存。mapshared_ptrboost::ptr_mapdb.clear();

于 2013-05-06T14:08:00.787 回答
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. 您可以插入一个空指针并稍后使用实际创建的值将其重置()(即,如果已存在具有此类键的值,则不实际创建对象)
于 2013-05-06T14:34:12.037 回答