More C++ Idioms/Const auto ptr
Const auto_ptr
編集
意図
編集リソース所有権の移動を防止する。
別名
編集動機
編集コード中で所有権を移動不可能にするという設計上の決定を、コンパイラの助けによって強制することが望ましいときがある。 ここで想定する所有権は、メモリやデータベースに対する接続のような任意のリソースに対するものである。 const auto_ptr イディオムは あるオブジェクトから別のオブジェクト、あるいはスコープ外へ、取得したリソースの所有権を移動させたくない場合に使用できる。
cv 修飾子(const と volatile を表す別名)なしの auto_ptr は、 所有権移動コンストラクタ(Move Constructor)イディオムで記述されているように、move semantics(代入やコピーにより所有権が移動する挙動)を持つ。 これは基本的に、代入の右辺のオブジェクトから左辺のオブジェクトにメモリの所有権が無条件に移動する、ということを意味する。 これにより、常にリソースの所有者が 1 つであることが保証される。 const auto_ptr はこの所有権の移動を防止できる。
解法とサンプルコード
編集メモリリソースを保持する auto_ptr を const として宣言する。
const auto_ptr <X> xptr (new X());
auto_ptr <X> yptr (xptr); // 不許可。コンパイルエラー。
xptr.release(); // 不許可。コンパイルエラー。
xptr.reset( new X() ); // 不許可。コンパイルエラー。
yptr のコピーコンストラクタは実際にはコピーコンストラクタではなく、 所有権移動コンストラクタ(Move Constructor)で記述されているように、 auto_ptr への 非 const 参照をとる所有権移動コンストラクタ(move constructor)である。 非 const 参照を const オブジェクトに束縛することはできないため、コンパイラはエラーを発する。 (訳註:また、代理(proxy)オブジェクトへの変換関数は非 const メンバ関数であるため const オブジェクトに対しては呼び出せず、代理(proxy)オブジェクトを経由することもできない)
影響
編集- const auto_ptr イディオムの望ましくない影響として、const auto_ptr をメンバに持つクラスに対して、コンパイラがデフォルトのコピーコンストラクタを提供できないことがある。これは、コンパイラが生成するコピーコンストラクタ中で各メンバのコピーを行う際、const auto_ptr を引数に取ることになるため、非 const 参照をとる所有権移動コンストラクタ(move constructor)のパラメータとして束縛できないからである。解法は、仮想コンストラクタ(Virtual Constructor)イディオムを使用するか、代入演算子とコピーコンストラクタに対するアクセスを禁止することで、コピーを明示的に禁止している boost::scoped_ptr を使用することである。