std::auto_ptr を採用して、class A のデストラクタを省略した場合、なにが起こるのか。そう、空からかわいい女のコが落ちてくるのだ。

まずは、(間違った)ヘッダファイル。

#ifndef A_HEADER
#define A_HEADER

#include <memory>

class A {

class Impl;
std::auto_ptr impl_;

public:
A();

void act();
};

#endif

このクラスのインスタンスを生成するようなコード、

int main(int, char* []) {

A a;
a.act();

return 0;
}

は、模式的には次のように展開される。

  1. class A の領域がスタックに確保される。
  2. 確保された領域に対して、class A のコンストラクタが実行される。
    1. class A のコンストラクタは、internal class A::Impl の領域をヒープに確保する。
    2. 確保された領域に対して、internal class A::Impl のコンストラクタが実行される。
    3. メンバ変数 impl_ は 確保された領域を参照するようになる。
  3. A::act() 関数が実行される。
    1. A::Impl::act() 関数が実行される。
  4. class A の implicit なデストラクタが実行される。
    1. メンバ変数 impl_ のために class std::auto_ptr のデストラクタが実行される。
    2. ヒープに確保された internal class A::impl の領域に対して delete が実行される。
    3. 定義が不完全な class のポインタを delete しようとした!

解決策は、必ず class A のデストラクタを定義することだ。それも、internal class A::Impl の定義が終わった後に。

さて、俺たちはここでそもそもの定義に戻ることになる。「変態」とは、コンパイル時の問題発見に拘泥する者たちのことだ。よろしい、俺たちは俺たちを信用しない。上記の問題は、class A のデストラクタを定義すれば回避できると判った。しかし、終わらない夜のなか、俺たちはデストラクタの定義を忘れてしまうかもしれない。そして、(仕様上)そのコードはコンパイルされてしまう。許されるべきではないことだ。許さないための方法として、boost::checked_delete(r) が存在する。そして、boost::scoped_ptr が存在する。俺たちが「変態」であるために、俺たちは boost::scoped_ptr を使わなければならない。最後に、それについて説明しよう。