5

同じアドレスを指す多くのポインターを使用するコードがあります。同等の簡単な例を考えると:

int *p =  new int(1);
int *q = p;
int *r = q;

delete r; r = NULL; // ok
// delete q; q = NULL; // NOT ok
// delete p; p = NULL; // NOT ok

複数の削除なしで安全に削除する方法は? すべて同じアドレスを指しているポインタを持つオブジェクトがたくさんある場合、これは特に困難です。

4

8 に答える 8

28

あなたのツールはshared_ptrライブラリのものboostです。ドキュメントを見てください:http ://www.boost.org/doc/libs/1_44_0/libs/smart_ptr/shared_ptr.htm

例:

void func() {
  boost::shared_ptr<int> p(new int(10));
  boost::shared_ptr<int> q(p);
  boost::shared_ptr<int> r(q);

  // will be destructed correctly when they go out of scope.
}
于 2010-10-14T10:55:41.303 に答える
18

答えは、管理されたポインターに頼ることなく、割り当てられた場所に基づいてポインターを削除するかどうかを知る必要があるということです。

あなたの例は一種の工夫ですが、実際のアプリケーションでは、メモリの割り当てを担当するオブジェクトがメモリの破棄を担当します。すでに初期化されたポインターを受け取り、それらを一時的に保存するメソッドと関数は、それらのポインターを削除しません。その責任は、最初にメモリを割り当てたオブジェクトにあります。

newへの呼び出しは、への呼び出しとバランスを取る必要があることを覚えておいてくださいdelete。メモリを割り当てるたびに、そのメモリの割り当てを解除するためにバランシングコード(多くの場合、デストラクタ)を作成する必要があることがわかります。

于 2010-10-14T10:58:47.420 に答える
10

「現代的な」答えは、スマートポインターを使用し、手動で削除しないことです。

boost::shared_ptr<int> p(new int(1));
boost::shared_ptr<int> q = p;
boost::shared_ptr<int> r = q;

物語の終わり!

于 2010-10-14T10:56:43.423 に答える
3

あなたが直面している問題は、プログラムの所有権のセマンティクスが明確でないことです。設計の観点から、各ステップでオブジェクトの所有者を判別してください。多くの場合、オブジェクトを作成した人は後でそれを削除する必要があることを意味しますが、所有権が譲渡されたり共有されたりする場合もあります。

メモリの所有者がわかったら、コードに戻って実装します。オブジェクトが別のオブジェクトの唯一の責任である場合、単一所有権のスマート ポインター ( std::auto_ptr/ unique_ptr) または raw ポインター (エラーの一般的な原因であるため、これを回避するようにしてください) を使用してオブジェクトを保持し、メモリを管理する必要があります。手動で。次に、他のオブジェクトへの参照またはポインタを渡します。所有権が譲渡されたら、スマート ポインター機能を使用して、オブジェクトを新しい所有者に渡します。所有権が本当に共有されている場合 (割り当てられたオブジェクトの明確な所有者がいない場合) shared_ptr、スマート ポインターを使用してメモリ管理を処理させることができます)。

于 2010-10-14T11:44:05.627 に答える
1

なぜポインタを勝手に削除しようとしているのですか? 動的に割り当てられるすべてのオブジェクトは、1 人の所有者によって 1 か所割り当てられます。そして、オブジェクトが再び削除されることを保証するのは、1 人の所有者の責任であるべきです。

場合によっては、所有権を別のオブジェクトまたはコンポーネントに譲渡したい場合があります。その場合、削除の責任も変わります。

また、所有権を忘れて共有所有権を使用したい場合もあります。オブジェクトを使用するすべての人が所有者 IP を共有し、少なくとも 1 人のユーザーが存在する限り、オブジェクトを削除しないでください。

次に、を使用しますshared_ptr

つまり、RAII を使用します。オブジェクトを手動で削除しようとしないでください。

于 2010-10-14T11:47:50.267 に答える
0

場合によっては、スマート ポインターが実際にアプリケーションの速度を低下させることがありますが、それほど大きくはありません。私がすることは、次のようにメソッドを作成することです:

void safeDelete(void **ptr)
{
  if(*ptr != NULL)
  {
     delete ptr;
     *ptr = NULL;
  }
}

100% 正しく実行したかどうかはわかりませんが、ポインターのポインターを受け取るこのメソッドにポインターを渡し、ポインターが指すポインターが NULL に設定されていないことを確認してから、オブジェクトを削除し、アドレスを 0 または NULL に設定します。これが良い方法ではない場合は訂正してください。私もこれに慣れていないので、複雑にならずにチェックするのに最適な方法だと誰かが言いました。

于 2012-06-24T18:05:41.777 に答える
0

スマート ポインターを使用できない (おそらく古いコードを処理している) 可能性がある非常にまれなケースがいくつかありますが、単純な「所有権」スキームも使用できません。

std::vector<whatever*>といくつかのポインターwhatever*が同じオブジェクトを指しているとします。安全なクリーンアップには、同じものを 2 回削除しないようにすることが含まstd::set<whatever*>れます。そのため、作成しながら を作成し、まだセットに含まれていないポインターのみを削除します。ポイントされたすべてのオブジェクトが削除されたら、両方のコンテナも安全に削除できます。

からの戻り値をinsert使用して、挿入されたアイテムが新しいかどうかを判断できます。私は以下をテストしていません(または std::set をしばらく使用していません)が、次は正しいと思います...

if (myset.insert (pointervalue).second)
{
  //  Value was successfully inserted as a new item
  delete pointervalue;
}

もちろん、これが必要になるようにプロジェクトを設計するべきではありませんが、回避できない場合でも、状況に対処するのはそれほど難しくありません。

于 2010-10-14T11:29:54.627 に答える
0

あなたの場合のように、ポインターによって参照されるメモリが既に削除されているかどうかを知ることはできません。
参照カウントを行うスマート ポインターでライブラリを使用できず、独自の参照カウント スキーマを実装できない場合 (投稿で説明したことを実際に実行する必要がある場合) は、ポインターで realloc を呼び出してみてください。
他の投稿で、実装によっては realloc の呼び出しがクラッシュせずに null ポインターが返される可能性があることを読みました。この場合、そのポインタが参照するメモリが解放されていることがわかります。
これが汚い解決策として機能する場合、移植性はありませんが、他に選択肢がない場合は試してください。もちろん、さらに悪いことは、アプリケーションをクラッシュさせることです:)

于 2010-10-14T13:13:43.837 に答える