12

私の理解では、 C ++ / CXはガベージコレクションを使用せず、代わりに参照カウントアプローチを使用します。

参照カウントの問題は、サイクルを破棄できないことです。サイクルは通常、標準C++のweak_ptrなどの弱参照を使用して解決されます。

しかし、C ++/CXで弱参照を明示的に指定する方法を見つけることができません。それから、これはC ++/CX自体によって処理されると思います。C ++/CXがこれをどのように解決するのか疑問に思っています。

たとえば、次のコードを見てください。

ref class Foo
{
public:
    Bar^ bar;
};

ref class Bar
{
public:
    Foo^ foo;
};

ref class App
{
public:
    virtual void OnLaunched(LaunchActivatedEventArgs^ args)
    {
        Foo^ foo = ref new Foo();
        Bar^ bar = ref new Bar();
        foo.bar = bar;
        bar.foo = foo;
    }
};

C ++ / CXはこのサイクルをどのように検出しますか?

C ++ / CXはこのサイクルをどのように解決しますか?

C ++ / CXは、これらのオブジェクトのどれを「ルートオブジェクト」にし、どれを「弱参照」にするかをどのように決定しますか?

4

6 に答える 6

12

簡単な答え:いいえ、C ++/CXはオブジェクトのサイクルを検出して解決しません。

長い答え:WinRT自体には、弱参照のための標準メカニズムがあります。IWeakReferenceABIレベルでは、これはインターフェイスとで定義されます。これはIWeakReferenceSource、「%ProgramFiles%\ Windows Kits \ 8.0 \ Include \ winrt\WeakReference.idl」で確認できます。

C ++ / CXでは、すべてのクラスが自動的に実装されるIWeakReferenceSourceため、すべてのインスタンスを弱く参照できます。オブジェクトへの弱参照を取得して保存するには、ヘルパークラスPlatform::WeakReference(vccorlib.hで定義)を使用する必要があります。

Foo^ foo = ref new Foo;
Platform::WeakReference weakRef(foo);

オブジェクトを取得するには、次を使用しますResolve<T>

foo = weakRef.Resolve<Foo>();

いつものようにnullptr、オブジェクトはすでに破棄されています。

それ以外は、インスタンスはWeakReference多かれ少なかれスマートポインタのように動作します。コピー可能、移動可能、比較可能、から割り当て可能でnullptrあり、不特定のブール型などに暗黙的に変換されます。

VS11ベータ版の時点では、IDE IntellisenseWeakReferenceを使用しようとすると、波線などで下線が引かれます。ただし、コンパイラはそれでも問題なく処理できます。

于 2011-09-17T08:05:09.990 に答える
1

SDKのInclude\winrt\WeakReference.hを確認してください。この目的に使用できるIWeakReferenceを定義します。

于 2011-09-16T22:06:12.787 に答える
0

これは、COMプログラミング、手動思考、および明示的なdecref呼び出しの追加と同じ古い方法になります。

于 2011-09-16T07:23:47.950 に答える
0

Pavel Minaevが言ったように、WinRTには、弱参照用の標準メカニズム(IWeakReferenceSource/IWeakReferenceインターフェイス、WRL::WeakRefヘルパークラスなど)があります。

残念ながら、を介して定義されたクラスref classは実装されておらずIWeakReferenceSource、少なくともこのDeveloper Previewバージョンでは、このインターフェイスを追加する方法を見つけることができませんでした。

考えられる回避策は、「ネイティブ」C++でC++/CX拡張機能を使用せずにWinRTクラスを実装することです。WRLフレームワークは、このタスクを大幅に簡素化します(WinRTの場合、ATLがCOMに対して行っていたことを実行します)。

WinRTサンプルの1つ(「DLLサーバーオーサリング」サンプル)は、使用せずにWinRTオブジェクトを実装する方法を示していますref。デフォルトでは、から継承するクラスはWRL::RuntimeClass<Interface>自動的に実装さIWeakReferenceSourceれるため、弱参照を提供します。

于 2011-10-05T16:21:50.340 に答える
0

MozillaXPCOMはベーコンのアプローチを実装しました。これは必要に応じてある程度WinRTに移植できます。一般に、ガベージコレクターのトレースを回避することは良いことです。開発者はまだメモリをリークする方法がたくさんあります、だから妄想に陥らないほうがいいです。また、制御の観点からは、循環的な所有権は意味がありません。それは、ミュンヒハウゼン症候群が自分の髪の毛で自分を泥沼から引き離し、空中に浮かんでいるようなものです。すべてのオブジェクトが存在する理由がなければならず、参照カウントはこの理由の現れです。もう1つの兆候は、変更する権利です。これにより、参照カウンターの可用性に大きく依存する堅牢なコピーオンライト技術が生まれます。トレースガベージコレクションしかない環境では、不要なミューテーションから保護するために可変データ構造のディープコピーを実行するか、小さな深い変更に対して大きなペナルティを伴う不変データ構造を使用する必要があります。または、可変および不変のデータ構造を前後に変換します。また、ガベージコレクションのトレースが推定されました使用可能なRAMが5倍ある場合にのみ正常に機能します(深くコピーされたレプリカは考慮されません)。それに比べて、保守的なアロケータは2倍の必要なRAMを使用します(断片化のために無駄になります)。だまされないでください。ガベージコレクターをコピーすると、割り当てが速くなりますが、同等のパフォーマンスを実現するには、参照カウントされた保守的なガベージコレクターの2.5倍のRAMが無駄になります。

アップルを見てください。彼らはTGCをオプション機能としてObjective-C2.0に導入しましたが、その後非推奨になり、多くのiPhoneアプリケーションがTGCなしで動作します。iPhoneは、優れたユーザーエクスペリエンスと長いバッテリー充電時間で知られています。Windows10は私の4GbRAMPCで地獄のようにフリーズしますが、Mac OS X10.4.10Hackintoshは1GbRAMで非常にスムーズに動作しました。多分これはどういうわけか関係があると思いませんか?どこかで誤ってメモリがリークされた可能性がありますが、最終的には、フリーズや大量のRAM消費に比べて観察が困難です。

RAMを大量に消費すると、プログラムはディスクにスワップされます。ディスクにスワップしてからガベージコレクションのトレースを開始すると、スワップされたページはすべてRAMに戻され、スワップされたページをRAMに戻すのは非常に遅くなります。また、そうするとき、他のアプリケーションのページはファイルを交換するためにプリエンプションされる必要があります。ご存知のように、ガベージコレクションされたアプリケーションのトレースは2.5倍のRAMを使用するため、これらのアプリケーションはスワップに行く可能性が2.5倍高くなります。突然、別のアプリケーションもガベージコレクションを開始し、スワップされたページをRAMに戻して、別のアプリケーションのページをプリエンプトする必要があります。そして、それは永久機関のように行き来し、その逆も同様です。通常の永久機関は薄い空気から無限にエネルギーを生成し、永久機関はその逆に無限にエネルギーを無駄にします。ガベージコレクションのトレースは、決して終わらないアルゴリズムです。それは時々ヒューリスティックに開始され、運が良ければそれが行われたときにのみ知られます。たぶん今回は幸運にも何かを集めることができます。2回目、3回目かもしれません。あなたは、PCが最終的にそのビジネスを完了し、最終的にあなたに仕事をさせてくれることを期待して、長い間PCを離れますが、このビジネスは決して終わりません。突然、2つのアプリケーションが同時にトレースガベージコレクションを実行し、スワップされていないRAMを求めて競合を開始します。ガベージコレクションをトレースすると、同じページに複数回アクセスする可能性が高いため、1つのページがスワップに何度も行き来する可能性があります。オフィス環境では、上司のPCだけが大量のRAMを搭載している可能性が高く、他のPCは可能な限り安価です。また、ウイルス対策はすべてのオフィスPCに強制的に導入されており、オフィスの従業員はそれを取り除くことはできません。アンチウイルスは、メモリ内の署名用にRAMを保持し、RAMをさらに少なくします。また、スワップファイルの駆動フリーズを含むすべてのI / Oをチェックして、完全に狂気に陥らせ​​ます。そこが地球の地獄です。

トレースガベージコレクターの支持者に、私のようにフリーズを観察できるかどうか尋ねたところ、PCに大量のRAM(ノートブックの16Gbなど)を入れ、シングルユーザーモードで使用し、ガベージコレクションを行うことがわかりました。このように彼らのためにうまく働きます。地獄では、彼らはウイルス対策を強制的に展開した最も安価なオフィスPCで開発に取り組む必要があります。

したがって、サイクル収集の問題だけを見ないことをお勧めします。参照カウントを愛することを学び、それを楽しんで、ユーザーにあなたのスリムなプログラムを楽しんでもらいましょう。参照カウントを最大限に活用します。ネストされた構造の堅牢なコピーオンライト。ラップされた接続を持つデータベース接続プール。ラッパーが参照されなくなったときに接続がすぐにプールに返されます。ネットワークの透過性。RAII。

また、他に選択肢がない場合は、MozillaXPCOMから借りてください。ちなみに、WindowsOSではMozillaXPCOMはMicrosoftCOMと同じABIを持っていると言われていますが、確かではありません。

于 2016-11-22T03:52:55.497 に答える
-5

これらはWinRTオブジェクトではなく、カスタムタイプのオブジェクトです。C ++ / CLI構文を使用してそれらを.NET参照型(ref class)として宣言したため、参照カウントではなく到達可能性テストを介して、すべての.NET参照型と同様にガベージコレクションされます。

Win32オブジェクトは常に参照カウントされているため、WinRTがそこで何も変更していないようです。これは、C ++ RAIIクラスを提供するだけであり、Win32プログラマーは、RAIIを利用するために独自のラッパーを作成しました。

于 2011-09-16T22:11:21.220 に答える