3

同じオブジェクトへのポインタを格納する2つのコンテナがあるとします。

std::list<Foo*> fooList;
std::vector<Foo*> fooVec;

そのメソッドが次の場合、これらのコンテナの1つからオブジェクトを1つ経由で削除するとします。

std::vector<Foo*>::iterator itr = 
  std::find( fooVec.begin(), fooVec.end(), pToObj );
fooVec.erase( itr );

CppReferenceは、これがオブジェクトのデストラクタを呼び出すと言っています。これは、のオブジェクトへのポインタfooListがダングリングポインタであることを意味しますか?

参照カウントポインタは使用したくない。この問題はどのように処理できますか?

4

5 に答える 5

6

いいえ。

コンテナーからポインターを削除すると、コンテナーからそのポインター値を取得するだけで、何も削除されません。(つまり、ポインターにはデストラクタがありません。)

ただし、コンテナ内に物事のポインタがあると危険です。検討:

std::vector<int*> v;
v.push_back(new int());
v.push_back(new int());
v.push_back(new int());

コンテナを通過してそれぞれを削除したことがない場合は、リークしています。さらに悪いことに、それは例外安全ではありません。ポインタコンテナを使用する必要があります。これにより、ポイントされたものが消去されたときに削除されます。(そして、コンテナが破壊されると、すべてが消去されます。)

しかし、あなたの場合、あなたはさまざまな場所でポインタを共有しているので、私は反対の議論を見ることができませんshared_ptr。それはまさにそれが作られたものです。

于 2010-07-24T18:12:16.797 に答える
1

オブジェクトのデストラクタが呼び出されるとは思いません。のポインタfooListは引き続き有効なデータを指している必要があります。

このリンクを参照している場合は、への呼び出しeraseによって、ベクトル内の後続の場所を指す可能性のあるイテレータが無効になる方法について説明しています。deleteただし、イテレータを無効にすることは、ベクトル内の1つを呼び出すこととは異なります。

于 2010-07-24T18:12:11.477 に答える
0

オブジェクトへの生のポインタがある場合、それを削除しない限り、デストラクタは呼び出されません。

オブジェクトが適切なタイミングで削除され、ポインタコンテナ(多くのアルゴリズムで必要とされる)を使用するために使用できるパターン(またはイディオムですか?)は、実際のオブジェクトを格納するために別の両端キューを使用することです。ポインタコンテナの後にdequeが破棄されていることを確認する必要があります。ベクトルの代わりにdequeを使用する必要がある理由は、以前に保存されたオブジェクトへのポインターを無効にすることなく、オブジェクトをdequeに追加できるためです。

于 2010-07-24T18:12:27.160 に答える
0

どちらのコンテナも(Foo *)オブジェクトへの参照を保持します。したがって、デストラクタが呼び出された場合、それはFooオブジェクト自体ではなく、ポインタオブジェクト(おそらく何もしません)のデストラクタです。(クラスFooの)元のオブジェクトは破棄されないため、ぶら下がっている参照はありません。

于 2010-07-24T18:14:06.913 に答える
0

この場合、コンテナに格納されているオブジェクトは元のポインタのコピーであり、元のポインタではありません。したがって、Foo*保存することにしたそれぞれに対して、3つのポインター(元の、1つは1つ、fooListもう1つはfooVec)があり、すべてがメモリー内の同じ場所を指しています。したがってerase、削除を呼び出すと、ポインター自体ではなく、ポインター自体で削除が呼び出され、ポインターの削除は無効になります(GManが言ったようなデストラクタはありません)。

于 2010-07-24T18:18:52.327 に答える