8

std::map文字列値を にマップするために使用していますMyType *。私のマップ宣言は次のようになります。

map<string, MyType *> *my_map = new map<string, MyType>;

my_map私のクラスの1つのプライベートメンバー変数です。私の問題は、マップを破壊する方法がわからないことです。deleteマップを削除するときは、マップに含まれるすべてのも呼び出したいと思いMyType *ます。ここに私の現在のデストラクタがあります:

my_map->erase(my_map->begin(), my_map->end());
delete my_map;

これにより、マップに含まれるポインターが削除されますか? それとも、erase を呼び出す前にマップを反復処理して各ポインターを削除する必要がありますか?

4

4 に答える 4

9

ポインターは単にポイントします。生のポインターを使用する場合、ポインターが指すリソースをアプリのどの部分が所有しているかを知る必要があります。それらがマップによって所有されている場合は、マップを反復処理し、マップが破棄される前に各ポインターで delete を呼び出す必要があります。ただし、コードの他の部分が所有するオブジェクトへのポインターをマップが保持するだけの場合は、何もする必要はありません。

より安全な解決策は、shared_ptr を使用してオブジェクトの有効期間を管理することです。これにより、最後の shared_ptr が破棄されたときにオブジェクトが適切に削除されることが保証されます。マップ内に shared_ptr を格納できます。他の shared_ptr インスタンスがマップ内のオブジェクトを参照していない場合は、必要に応じて、マップが破棄されるときにオブジェクトが破棄されます。

于 2013-07-25T14:54:40.050 に答える
4

これにより、マップに含まれるポインターが削除されますか [...]?

いいえ、提供したコードを考えると、マップのすべてのメンバーがリークします。

原則として、すべてnewに一致するdelete. マップには がありますがdelete、その中の要素にはありません。

この問題に対する最も正しい解決策は、動的割り当てをまったく使用しないことです。MyType可能であれば、sディレクトリを保存するだけです:

map<string, MyType>

...そして、それ自体を動的に割り当てる代わりにmap、自動的に保存します:

map<string,MyType> my_map;

何らかの理由で自動ストレージ期間が不可能な場合は、動的割り当てにスマート ポインターを使用します。C++11 コンパイラの場合、 の要素にunique_ptr(または、まれに、shared_ptrまたは さえも) を使用します。weak_ptrmap

map<string, unique_ptr<MyType>> my_map;

(C++03 コンパイラの場合は、それに相当する Boost を使用します。) 次に、my_mapが破棄されると、すべての要素がdeleted になります。

これをすべてむき出しにして、上記のいずれもうまくいかない状況にある場合 (私は非常に疑わしいと思います)、自分でマップを反復する必要があります。

struct deleter
{
  template <typename T> operator() (const T& rhs) const
  { 
    delete rhs.second;
  }
};

for_each (my_map->begin(), my_map->end(), deleter());

C++11 では、これを次のようなラムダにすることができます。

for_each (my_map->begin(), my_map->end(), [](auto item) -> void
{
  delete item.second;
});
于 2013-07-25T15:02:11.487 に答える
4

生のポインターの代わりにスマート ポインターを使用すると、すべてが自動的にクリーンアップされます。

// header:
using MapType = std::map<std::string, std::shared_ptr<MyType>>;
shared_ptr<MapType> my_map;

// usage:
my_map.emplace("foo", std::make_shared<MyType>());

// destructor:
MyClass::~MyClass()
{
    // nothing!
}
于 2013-07-25T14:57:55.363 に答える
2

最新の C++ では、作業を楽にして、厳密に必要な場合にのみポインターを使用してください。

次のコードから始めました。

map<string, MyType *> *my_map = new map<string, MyType>;

最初にできることは、インスタンスへのポインターstd::mapではなく、インスタンスをデータ メンバーとして使用することを検討することです。

次に、MyTypeをコピーするのにそれほど費用がかからず、そのインスタンスがマップによってのみ所有されている場合は、単純なmapfrom stringto MyType(の代わりにMyType*) を検討してください。

// my_map data member - no pointers --> automatically deleted in class destructor
map<string, MyType> my_map;

ポインターを含むマップが本当に必要な場合は、(C++11/14 で利用可能) 共有所有権または一意の非共有所有権のようなスマート ポインターの使用を検討してください。 (C++98/03 を対象とする場合、オプションは を使用することです。移動セマンティクスがないため、移動セマンティクス機能に大きく基づいている を使用することはできません。) 例:std::shared_ptrstd::unique_ptr
boost::shared_ptrunique_ptr

// Map containing _smart_ pointers 
//     --> default destructor is fine (no need for custom delete code)
map<string, shared_ptr<MyType>> my_map;

ご覧のとおり、 (生のポインターの代わりに)値セマンティクスまたはスマート ポインターを使用すると、コードを簡素化し、C++ が提供する自動破棄を使用できます。

于 2013-07-25T15:12:23.590 に答える