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_ptrまたはstd::shared_ptr(C++ 11、C ++ 03の場合、コンテナが壊れているためコンテナで使用する ことはありませんが、代わりにスマートポインタstd::auto_ptrを安全に使用できます)。boost

したがって、あなたのmapタイプは次のようになります。std::map<int, std::unique_ptr<abstractclass>>. オブジェクトがマップから削除されると、スマート ポインターが自動的にそれを処理します。

もう1つの解決策は、deleteすべてのアイテムを自分で作成することです(@MarkBが言ったように)が、これは非常にエラーが発生しやすいため、通常、可能な場合はスマートポインターが優先されます。

于 2013-05-06T14:10:33.207 に答える
4

仮想デストラクタがある限りabstractclass、コンテナ内のすべてのアイテムとアイテムdeletesecondコンポーネントを単純に反復してメモリを解放できます。これを行うには複数の方法があります。たとえば、for ループ、またはfor_eachファンクターまたはラムダを使用します。

編集: さらに調べてみると、ここではマップが所有権を持っているようです。 (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. 空のポインターを挿入し、後で実際に作成された値で reset() することができます (つまり、そのようなキーを持つ値が既に存在する場合、実際にはオブジェクトを作成しません)。
于 2013-05-06T14:34:12.037 に答える