RAIIとは?例?


19

RAIIという用語が使用されるときは常に、人々は実際には初期化の代わりに脱構築について話しています。私はそれが何を意味するのかを基本的に理解していると思いますが、よくわかりません。また、C ++は唯一のRAII言語ですか?JavaまたはC#/。NETはどうですか?

回答:


25

Resource Acquisition Is Initializationは、オブジェクトがそれ自体を完全なパッケージと見なし、他のコードがインスタンスに「ちなみに、すぐにクリーンアップする予定です-今すぐ片付けてください」と伝えることを期待しないことを意味します。通常、デストラクタに意味のあるものがあることを意味します。また、例外をスローするなど、予測が困難な特定の状況ではデストラクタの実行を期待できることを認識して、リソースを管理するためのクラスを作成することも意味します。

Windowsカーソルを待機(砂時計、ドーナツ型の非動作など)カーソルに変更するコードを記述し、作業を行ってから元に戻すコードを記述したいとします。また、「あなたの仕事をする」が例外をスローするかもしれないと言ってください。RAIIの方法は、カーソルが待機するように設定するクラス、希望する処理を実行する「実際の」メソッド、およびカーソルを戻すクラスを作成することです。リソース(この場合はカーソル状態)はオブジェクトのスコープに関連付けられています。リソースを取得すると、オブジェクトを初期化します。例外がスローされた場合、オブジェクトが破壊されることを期待できます。つまり、リソースをクリーンアップすることを期待できます。

RAIIを上手に使用することは、必要ないということですfinally。もちろん、それは決定論的な破壊に依存していますが、これはJavaではできません。C#およびVB.NETでは、を使用して、一種の決定論的な破壊を取得できますusing


4
私はこれがあなたが得ているものだと思いますが、JavaとC#がRAIIをサポートしない理由はガベージコレクタのためだと付け加えたいかもしれません。C ++では、ローカルオブジェクトはスコープから外れるとすぐに破棄されます。Java / C#では、これは正しくありません。
ジェイソンベイカー

Jasonsポイントを拡張すると、JavaとC#がタイムリーな破壊を保証できない理由は、参照サイクルの可能性のためです。つまり、デストラクタを実行する安全な順序を決定することは不可能です。参照サイクルはC ++でも発生する可能性がありますが、意味は異なります-プログラマーは破壊順序を決定し、明示的な削除を行う責任を負います。その責任は、多くの場合、いくつかの上位クラスのデストラクタにまとめられています。たとえば、コンテナクラスは、含まれているすべてのアイテムが確実に破壊されるようにします。「所有権」が重要です。
Steve314

1
@Jasonは、「決定論的破壊」が意味するものです。C++プログラマは、デストラクタがいつ実行されるかを知っています。
ケイトグレゴリー

私はこれが古い答えであることを知っていますが、私はまだいくらか混乱しています。この用語を知ったばかりで、情報はコンストラクターで取得する必要があると言っています。それは私には本当に理にかなっておらず、この答えはそれと矛盾しているようですが、あなたは明確にできますか?
パーヨハンソン

1
@PerJohanssonはい、あなたは俳優で獲得します。そして、dtorでリリースします。私は2番目の点に焦点を合わせていましたが、それらは一緒に行きます。アクターが完了すると、有効なオブジェクトがあることがわかります。そして、あなたは何が起こっても、リソースは適切なタイミングでリリースされることを知っています。
ケイトグレゴリー

4

RAIIは、オブジェクトのクリーンアップの責任をいつ取るかを部分的に決定します。ルールは、コンストラクタの初期化が完了したときにオブジェクトが責任を負うというルールです。初期化とクリーンアップ、コンストラクターとデストラクターの対称性は、2つが互いに密接な関係にあることを意味します。

RAIIの1つのポイントは、例外の安全性を確保することです。例外がスローされても、アプリケーションは自己整合性を保ちます。一見、これは簡単です-例外がスコープを終了させる場合、そのスコープ内のローカル変数を破棄する必要があります。

しかし、コンストラクター内で例外スローが発生するとどうなりますか?

さて、オブジェクトは完全に構築されていないため、安全に破壊することはできません。コンストラクターは、例外が伝播される前に必要なクリーンアップが行われるように、必要に応じてtryブロックを用意する必要があります。オブジェクトが構築されたスコープの外で例外が伝播すると、オブジェクトはそもそも構築されなかったため、デストラクタ呼び出しはありません。

特に、破棄されるオブジェクト内のメンバーデータのコンストラクターを検討してください。これらのいずれかが例外をスローした場合、メインコンストラクターコードはまったく実行されませんが、そのコンストラクターの暗黙的な部分を形成する一部のコードは実行されます。正常に構築されたメンバーはすべて自動的に破棄されます。構築されなかったメンバー(例外をスローしたメンバーを含む)はそうではありません。

基本的に、RAIIは、特に例外がスローされた場合に、完全に構築されたすべてのものがタイムリーに破壊され、オブジェクトが完全に構築されたかそうでないかを保証するポリシーです。安全にクリーンアップする方法がわからない構築されたオブジェクト)。割り当てられたリソースも解放されます。また、多くの作業は自動化されているため、プログラマーはあまり気にする必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.