ここで議論に追加します。
ガベージ コレクションには既知の問題があり、それらを理解すると、C++ に問題がない理由を理解するのに役立ちます。
1.パフォーマンス?
多くの場合、最初の不満はパフォーマンスに関するものですが、ほとんどの人は自分が何について話しているのかを本当に理解していません。問題が示すようにMartin Beckett
、パフォーマンス自体ではなく、パフォーマンスの予測可能性です。
現在、広く展開されている GC には 2 つのファミリがあります。
のMark And Sweep
方が高速ですが (全体的なパフォーマンスへの影響が少ない)、「世界がフリーズする」症候群に悩まされます。つまり、GC が開始されると、GC がクリーンアップを行うまで他のすべてが停止します。数ミリ秒で応答するサーバーを構築したい場合...一部のトランザクションは期待に応えられません:)
問題Reference Counting
は異なります。アトミックカウントが必要なため、特にマルチスレッド環境では、参照カウントによってオーバーヘッドが増加します。さらに、参照サイクルの問題があるため、それらのサイクルを検出して排除するための巧妙なアルゴリズムが必要です (一般的には、頻度は低くなりますが、「世界を凍結する」ことによっても実装されます)。一般に、今日の時点では、この種の (通常はより応答性が高く、むしろフリーズする頻度は低くなりますが) はMark And Sweep
.
「Freeze The World」の側面がない場合Reference Counting
と同様のグローバル パフォーマンスを持つガベージ コレクターを実装しようとしている Eiffel の実装者による論文を見たことがあります。Mark And Sweep
GC 用に別のスレッドが必要でした (標準)。アルゴリズムは(最後に)少し恐ろしいものでしたが、この論文は概念を 1 つずつ紹介し、「単純な」バージョンから本格的なバージョンへのアルゴリズムの進化を示すという点で優れていました。PDFファイルに手を戻すことができれば読むことをお勧めします...
2. リソースの取得は初期化 (RAII)
C++
リソースの所有権をオブジェクト内にラップして、それらが適切に解放されるようにするという点で、これは一般的なイディオムです。ガベージコレクションがないため、主にメモリに使用されますが、他の多くの状況でも役立ちます。
- ロック (マルチスレッド、ファイルハンドルなど)
- 接続 (データベース、別のサーバーなどへ)
アイデアは、オブジェクトの有効期間を適切に制御することです。
- あなたがそれを必要とする限り、それは生きているべきです
- 使い終わったら殺すべき
GC の問題は、GC が前者に役立ち、最終的に後でそれを保証する場合...この「究極」では十分ではない可能性があることです。ロックを解除する場合は、それ以上の呼び出しがブロックされないように、すぐに解除してください。
GC を使用する言語には、次の 2 つの回避策があります。
- スタック割り当てが十分な場合は GC を使用しないでください。通常はパフォーマンスの問題のためですが、スコープが有効期間を定義するため、このケースでは本当に役立ちます
using
構造...しかし、それは明示的な(弱い)RAIIですが、C++ではRAIIは暗黙的であるため、ユーザーは無意識のうちにエラーを起こすことはできません(using
キーワードを省略して)
3.スマートポインター
スマート ポインターは、多くの場合、.NET でメモリを処理するための特効薬として登場しC++
ます。スマート ポインターがあるので、結局 GC は必要ないという話をよく耳にします。
これ以上の間違いはありません。
スマート ポインターは役立ちます。RAII の概念auto_ptr
を使用すると、非常に便利です。unique_ptr
それらは非常に単純なので、自分で簡単に書くことができます。
所有権を共有する必要がある場合、それはより困難になります。複数のスレッド間で共有する場合があり、カウントの処理にはいくつかの微妙な問題があります。したがって、自然に の方に向かいshared_ptr
ます。
それは素晴らしいことです。結局のところ、それがBoostの目的ですが、特効薬ではありません. 実際、主な問題shared_ptr
は、によって実装されたGCをエミュレートするReference Counting
ことですが、サイクル検出をすべて自分で実装する必要があります... Urg
もちろんweak_ptr
、これはありますが、残念ながらshared_ptr
、これらのサイクルのために を使用しているにもかかわらず、メモリ リークが発生していることをすでに確認しています...そして、マルチスレッド環境にいる場合、検出するのは非常に困難です!
4. 解決策は何ですか?
特効薬はありませんが、いつものように、確実に実現可能です。GC がない場合、所有権を明確にする必要があります。
- 可能であれば、一度に 1 人の所有者を持つことを好む
- そうでない場合は、クラス図に所有権に関するサイクルがないことを確認し、
weak_ptr
確かに、GC があれば素晴らしいことですが、それは些細な問題ではありません。それまでの間は、袖をまくり上げる必要があります。