1. ホーム
  2. c++

RAIIとガベージコレクタの比較

2023-09-23 03:45:33

質問

私は最近、CppCon 2016 で Herb Sutter 氏による "Leak Free C++..." についての素晴らしい講演を見ました。彼は、スマート ポインターを使用して RAII (Resource acquisition is initialization) - Concepts を実装し、それらがメモリ リークの問題の大半を解決する方法について語っています。

今、私は疑問に思いました。RAII のルールを厳密に守れば、それは良いことのように思えますが、なぜ C++ でガベージコレクタを持つことと違いがあるのでしょうか。RAII では、プログラマがリソースを再び解放するタイミングを完全に制御できることは知っていますが、これはガベージコレクタを持つことよりも有益なのでしょうか。本当に効率が悪くなるのでしょうか?ガベージコレクタを持つことは、コード上の小さなメモリ断片を解放する代わりに、一度に大きなメモリチャンクを解放することができるので、より効率的であるとさえ聞いています。

どのように解決するのですか?

RAII のルールを厳密に守れば、それは良いことのように思えますが、なぜ C++ でガベージコレクタを持つことと違いがあるのでしょうか?

どちらもアロケーションを処理しますが、その方法はまったく異なります。Java のような GC を指しているのであれば、それは独自のオーバーヘッドを追加し、リソース解放プロセスから決定論の一部を削除し、循環参照を処理します。

しかし、特定のケースのためにGCを実装することができ、はるかに異なるパフォーマンス特性を持つことができます。私はかつて、高性能/高スループットのサーバーで、ソケット接続を閉じるために 1 つを実装しました (単にソケットクローズ API を呼び出すと時間がかかりすぎ、スループット パフォーマンスが損なわれました)。これは、メモリではなく、ネットワーク接続と、周期的な依存関係の処理を必要としました。

RAII では、プログラマはリソースが再び解放されるタイミングを完全に制御できることは知っていますが、それはいかなる場合でもガベージコレクタを持つことよりも有益なのでしょうか?

この決定論は、GCが単純に許さない機能です。時々、あなたは が欲しい ある時点以降に、クリーンアップ操作が実行されたことを知ることができるようにしたい場合があります (一時ファイルを削除する、ネットワーク接続を閉じるなど)。

このような場合、GCでは不十分であり、C#では(例えば)、このような理由で IDisposable インターフェイスがあります。

ガベージコレクタがあれば、コード中の小さなメモリ断片を解放する代わりに、一度に大きなメモリチャンクを解放できるので、より効率的だとも聞いています。

できる......実装に依存する。