典型的な用法
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/07/14 06:48 UTC 版)
RAIIの最も基本的な活用例は、動的確保されたメモリを自動解放するスマートポインタ (smart pointer) である。C++においてnew演算子(またはnew[]演算子)で動的に確保されたメモリは、不要になったときにその領域を指すポインタを経由してdelete演算子(またはdelete[]演算子)で明示的に解放しなければならない。もし解放忘れがあるとメモリリークにつながるが、解放忘れがないように細心の注意を払って、コードパスに手動でひとつひとつ削除処理を記述していくことは非常に手間がかかる。一方、C++ではオブジェクトをスタックに割り当てることも可能であり、動的確保されたメモリを指すポインタをラップするスマートポインタクラスのオブジェクトをスタックに割り当て、ラッパーオブジェクトの寿命が尽きた時点で自動的に呼び出されるデストラクタを利用することにより、動的確保されたメモリの解放を明示的に逐一記述することなく、暗黙的かつ確実に実行させることができる。標準C++ライブラリにおける動的配列クラステンプレートのstd::vectorなども、プログラマが明示的にnew[]およびdelete[]を呼び出す必要のないRAIIクラスの一種である。 RAIIはファイル操作にも用いられる。C言語ではファイルアクセスの際、fopen()関数により取得したFILEオブジェクトを明示的にfclose()関数で解放することでファイルを閉じる必要があったが、標準C++ライブラリのファイルストリームでは、オブジェクトのコンストラクタでファイルストリームを開き、デストラクタで閉じることで、ファイルハンドルの管理を自動化し、リソースリークを防ぐことができる。このようなファイルアクセスの管理に限らず、C++のデストラクタ機構はあらゆるリソースの寿命管理に活用できる。ほかには、マルチスレッドアプリケーションにおいてクリティカルセクションのロックの管理にもよく用いられる。C++03規格以前においても、Boost C++ライブラリやMicrosoft Foundation Classライブラリなどにクリティカルセクション管理用のRAIIクラスが用意されていたが、C++11規格でスレッドおよび同期オブジェクトが標準化された際に、類似のRAIIクラスがstd::lock_guardおよびstd::unique_lockとして導入された。 また、動的に確保されたメモリの所有権もRAIIで管理できる。所有権が唯一となるスマートポインタクラステンプレートとして、C++03までの標準C++ライブラリではstd::auto_ptrが用意されていたが、C++11以降では非推奨となり、代替のstd::unique_ptrが用意されている。Boost C++ライブラリには類似のクラステンプレートとしてboost::scoped_ptrやboost::interprocess::unique_ptrが実装されている。また、参照カウント方式で所有権を共有するオブジェクトのスマートポインタクラステンプレートとして、Boost C++ライブラリのboost::shared_ptrがある。これはC++11にてstd::shared_ptrとして標準化された。shared_ptrとともに利用する弱参照スマートポインタとして、それぞれboost::weak_ptrおよびstd::weak_ptrが存在する。そのほか、侵入型参照カウント方式のboost::intrusive_ptr、Loki(英語版)のポリシーベースのLoki::SmartPtr、COMインターフェイスオブジェクト (IUnknown) の参照カウント管理に特化したATLのATL::CComPtrなどがある。 後の例のようにRAIIは例外安全の達成にも活用される。RAIIを使えばあちこちにtry-catchブロックを記述することなくメモリリークやリソースリークを防げる。
※この「典型的な用法」の解説は、「RAII」の解説の一部です。
「典型的な用法」を含む「RAII」の記事については、「RAII」の概要を参照ください。
- 典型的な用法のページへのリンク