18

オペレーターへの呼び出しdeleteが同期的かどうか疑問に思っていました。言い換えれば、もしそうなら:

delete p;

C++ 標準は、この呼び出しが実行を終了した後にのみメモリが解放されることを保証しますか? それとも、呼び出しは非同期で、OS がメモリを解放するのに最適な時期であると判断したらすぐにタスクをスケジュールして、このメモリを解放するだけですか?

最初のケースが有効な場合、独自の非同期削除機能を実装する必要があるということですか? ほとんどの場合、私たち (プログラマー) はメモリがいつ正確に解放されるかを気にしないため、コードがフリーズしてこれを待つ必要はありません (おそらく費用がかかりますか?)。終了するシステム コールではなく、削除するタスクをスケジュールし、すぐに実行を続行します。C++ は、車輪を再発明せずにこれを行うための標準機能を (おそらく標準ライブラリを介して) 提供していますか?

4

4 に答える 4

18

delete同期です。これは、基になるメモリがその時点でオペレーティング システムによって実際に解放されるという意味ではありませんが、C++ システムの観点からは、あたかも解放されたかのように動作します。

ほとんどの場合、私たち(プログラマー)はメモリがいつ解放されるかを気にしないと言うので、私は尋ねています

しかしdelete、それは主にメモリに関するものではなく、決定論的な方法でデストラクタを呼び出すことに関するものでもあります。これは、メモリに限定されない汎用のリソース解放メカニズムです。そして、ここで同期性を持つこと重要です。同期性がないと、C++ の中核的な側面の 1 つであるRAIIが機能しません。

于 2013-04-15T20:40:46.950 に答える
7

delete p;メモリが解放されて OS に戻ることを保証するものはありません。実際、かなりの数の (ほとんどの?) 実装では、そのようなことは何もしません。

ただし、呼び出し時に発生する正確な量deleteさまざまです。場合によっては、ほぼ瞬時に発生します (ブロックを空きメモリ ブロックのリストにリンクするだけです)。オブジェクトを破棄し、現在の空きリストを検索して、解放されるブロックと合体できる隣接ブロックを探します。

于 2013-04-15T20:42:39.563 に答える
4

あなたに関する限り、すべてが期待どおりに動作し、隠れたトラップや落とし穴はありません。T * p = new T; delete p;これがどのような状況で発生したとしても、いつでも言うことができ、それは正しいです。

オペレーティング システムが日常的にあらゆる種類のプロセスとスレッドに同時にメモリを割り当てる必要があることを考えると、その問題は既に正しく解決されていると考えることができます。

より正式には、18.6.1.4/1 (「データ競合」) は次のように述べています。

データ競合の存在を判断する目的で、 のライブラリ バージョンoperator new、 global のユーザー置換バージョンoperator new、および C 標準ライブラリ関数は、戻り値によって参照されるストレージのみにアクセスして変更したかのように動作するものとしますcallocmallocのライブラリ バージョンoperator delete、 のユーザー置換バージョンoperator delete、および C 標準ライブラリ関数freeは、最初の引数によって参照されるストレージのみにアクセスして変更したかのように動作します。

「ブロック性」について: 要するに、C ライブラリの割り当て関数が何をするかということです。「この関数は何らかのメモリへのポインタを返す」以外には何も指定されていません。メモリ割り当てをどのように提供するかは、プラットフォーム次第です。

于 2013-04-15T20:37:24.537 に答える
0

C/C++ でのフリー コールは、何があってもすでに非常に高速です。その点で、より適切な時期に削除を遅らせる理由はありません。そのために必要な簿記は、実際の無料通話時間を相殺する以上のものです.

デストラクタが DB 接続のソケットを閉じるなどの作業を行う場合、そのタイプの作業を後で行うことができますが、それはより例外的なケースである必要があります。

于 2013-04-15T20:42:22.867 に答える