2017-02-04 7 views
2

依存関係注入では、クラスの依存関係は呼び出し元によってインスタンス化され、渡されます。多くの場合、コンストラクタ引数として渡されます。これは依存関係の寿命の終わりを心配する必要がないので、管理されたヒープを持つ言語でうまく機能します。しかし、他の種類の言語はどうですか?マネージヒープなしでDIを使用できますか?

たとえば、従来のmallocおよびfree環境では、一般にメモリを割り当てる方法でも解放する必要があります。私はそれがどのようにDIで達成されるのか分かりません。

または参照カウントを必要とするメモリ方式、たとえば、 COMでは、呼び出し元がReleaseを依存関係に呼び出すとき、または注入を受け取るオブジェクトがReleaseを2回呼び出す必要があるかどうかはわかりません。

マネージヒープなしでDIを使用することはできますか?その場合、リソースが正しく解放されるように、どのコードパターンがうまく機能しますか?

+0

はい、クラスインスタンスが破棄されたときに、単に挿入されたオブジェクトを破棄することができます。 –

+0

管理対象環境と非管理対象環境の両方で、リソースの作成と確定的なクリーンアップを制御するのは[Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot/)です。管理されていない環境ではこれはもう少し多くの作業を意味しますが、コンポーネントの作成とメモリの解放を行うのはComposition Rootです。 – Steven

答えて

1

しかし、他の種類の言語についてはどうですか?マネージヒープなしでDIを使用することは可能ですか?マネージヒープを持つ

はDIのための前提条件ではありません。例えばC++はマネージ言語ではありませんが、JavaやC#のようなマネージド言語のDIフレームワークに匹敵するDIフレームワークもあります。

ダニエルPallastrelliの優れたプレゼンテーションはGoing native with less coupling - Dependency Injection in C++詳細に他の二つのデカップリング技術(工場やサービスロケータ)を超えるDIのメリットを説明しています。また、Wallarooと呼ばれるC++ DIフレームワークを紹介し、その内部についても説明します。

もう1つのC++ DIフレームワークは、別のアプローチに基づいて、Wallarooは[Boost].DIです。はじめにの章を読むことを強くお勧めします。 「依存性注入は既に使用していますか?」、「依存性注入は必要ですか?」などの短い質問ですが、良い答えです。

3番目のC++ DIフレームワークはInfector++です。

これらは、そこにある多くのC++ DIフレームワークのうちの3つに過ぎません。 this pageにリストされているものはたくさんあります。C++、彼らは広く受け入れられているかどうどんなにための非常に多くのDIフレームワークが存在する場合

私のポイントは、あり、:-)マネージヒープなしDIを持つことが確実に可能である

その場合、リソースが正しく解放されるように、どのコードパターンがうまく機能しますか?

上記のリンクは完全なDIフレームワークは、依存関係の解決、異なる創造ポリシーとオブジェクトのスコープと最終的には、あなたの質問、オブジェクトのライフサイクル管理を含むC++で行うことができる方法についての追加の入力を提供しています。

ここでは、ライフサイクル管理を一貫して確定的に行う方法をで紹介します。前述のフレームワークはすべてスマートポインタ(std::unique_ptr,std::shared_ptr、さらにはBoostサポートを提供する場合はboost::shared_ptr)を使用し、それらに作成ポリシーのセマンティクスを添付します。 このパターンを使用するには完全なDIフレームワークは必要ありません。基本的な考え方はとても簡単です。

は、私は、次のいずれかのようクラスを宣言したとします

class i_depend_on_others { 
    i_depend_on_others(std::unique_ptr<other>, 
         std::shared_ptr<another_other>, 
         boost::shared_ptr<yet_another_other>) 
    { } 
}; 

これは明確なコンストラクタ・インジェクションですが、「その他」の予想寿命に関する追加セマンティックと。最初のotheri_depend_on_othersインスタンスが所有し、std::unique_ptrがあるので、i_depend_on_othersインスタンスが削除されるとすぐに削除されます。 another_otheryet_another_otherは、i_depend_on_othersインスタンスとは独立したライフサイクルを持つと予想されます。このパターンは、リソースをクリーニングする責任を負うi_depend_on_othersインスタンスがいつ定義されているのか、そして呼び出しコードがそれを行うべきときを明確に定義します。 (DIフレームワークの場合は、フレームワークは、共有インスタンスの世話をする)

を疑問は、この場合には何をすべきかです:

class i_depend_on_others_as_well { 
    i_depend_on_others_as_well(other*) { } 
}; 

(私は生のポインタがすべきことをここで主張スキップます現代のC++開発では避けるべきです。それらを使うことを余儀なくされているとしましょう。) ここでも、パターンは明確なセマンティクスを定義しています。 生ポインタは所有権移転を意味します。i_depend_on_others_as_wellのインスタンスはotherを削除する責任があります。

[Boost].DIのようなDIフレームワークの場合、ポインタのタイプによって、挿入されたオブジェクトのデフォルトのライフサイクルが決まります。共有ポインターの場合、シングルトンとなり、[ブースト] .DIによって一度作成され、維持され、生ポインタと一意のポインターについては、毎回新しいインスタンスが作成されます。

このパターンの詳細については、[Boost] .DIドキュメントの"Decide the life times"の章を参照してください。

1

DIとガベージコレクションは関係ありません。メモリ管理を整理するだけで済みます。どこからでも静的オブジェクトを使用しようとすることから始めます。これは、DIグラフが静的である(つまり、アプリケーションの作業中に変更されていない)場合に機能します。

DIグラフが進化している場合や、アプリケーションの起動時にその構造が決定された場合、これをどのように行う必要があるかについての詳細情報が必要です。私はすべての場合に適合する一般的な解決策が可能であるとは確信していません。 DIグラフを変更するエンティティがクリーンアップを担当する必要があります。他のケースではC++で行われているのとまったく同じ方法です。たとえば、DIプロキシオブジェクトを静的なコンテナに配置して、アプリケーションの終了時に破壊されます(そして、すべてが適切に構成されている場合)。

C/C++では、このやり方でコンテナや接続などの管理にメモリ管理が必要です。私はなぜDIが特別なのか分かりません。ガベージコレクションは、それが使用されているすべてのものについて、メモリ管理を解決します(まだそれ自身の欠点があります)。

関連する問題