More C++ Idioms/チェック付きdelete(Checked delete)
表示
チェック付きdelete(Checked delete)
[編集]意図
[編集]delete 式の安全性を向上する。
別名
[編集]動機
[編集]C++ 標準は 5.3.5/5 において、delete 式によって、不完全なクラス型へのポインタを delete することを認めている。 自明でないデストラクタか、クラス独自の delete 演算子を持つクラスの場合、未定義動作となる。 不完全型が delete されるとき、警告を出すコンパイラもあるが、不幸なことに全てのコンパイラではなく、また、プログラマは警告を無効にしたり無視する場合がある。
解法とサンプルコード
[編集]チェック付きdelete(Checked delete)イディオムは、delete 対象の型が不完全型の場合にコンパイラにエラーを出すことを強制する。 下記のコードは boost 中の checked_delete 関数テンプレートの実装である。 型 T が定義されていない場合、例えば、前方宣言しかない場合等に、負の要素数となる配列を宣言することでコンパイラにエラーを出すことを強制する。
template<class T>
inline void checked_delete(T * x)
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
template<class T>
struct checked_deleter : std::unary_function <T *, void>
{
void operator()(T * x) const
{
boost::checked_delete(x);
}
};
これらの関数テンプレート、クラステンプレートにより、完全型が要求され、さもなくばコンパイルエラーが生じることで、問題を避けられる。 配列に対する delete 演算子でも同様に適用可能である。
注意 std::auto_ptr はチェック付き delete のようなものは全く使っていない。 そのため、不完全型によって std::auto_ptr をインスタンス化し、std::auto_ptr の宣言時点(point of declaration)でテンプレートパラメータの型が不完全である場合には、デストラクタ中で未定義動作を引き起こすかもしれない。