# 以下の内容は VS2005 の VC++(8.0)で確認したものです。
# 他のバージョンや他処理系では動作に違いがあるかも知れません。
auto_ptr は C++ インスタンスの寿命(生成/開放)を管理するテンプレートで,
auto_ptr<SomeClass> aPtr(new SomeClass());
のように宣言しておくと,メソッド終了時などにインスタンスを開放してくれる訳ですが,この宣言を
auto_ptr<SomeClass> aPtr = new SomeClass();とやってしまうと,実行時に Access Vioration で落ちてしまいます。
コンパイル時にはエラーや警告など,一切出ません。
で,理由が分からずに深く悩んだりします(^^;
仕方ないので出力されたコードを調べてみると,ポインタの代入時に auto_ptr_ref というクラスへの変換が挿入されてしまっているのが分かります。
auto_ptraPtr = auot_ptr_ref (new SomeClass();)
だいたいこんなイメージです(厳密にはちょっと違いますが)。
auto_ptr
これでうまく動くのならばOKなのですが,実際のコードはポインタの参照値がポインタとして扱われてしまっていて(SomeClass** として参照されていて),アクセスした時点でダウン,という構造になっています。
で,この auto_ptr_ref というクラス,ドキュメントにも記載されていない内部定義のようですが,どうにも実装が怪しい。
// TEMPLATE CLASS auto_ptr
template<class _Ty>
class auto_ptr;
template<class _Ty>
struct auto_ptr_ref
{ // proxy reference for auto_ptr copying
auto_ptr_ref(void *_Right)
: _Ref(_Right)
{ // construct from generic pointer to auto_ptr ptr
}
void *_Ref; // generic pointer to auto_ptr ptr
};
auto_ptr の宣言がこれに続くのですが,これを見ただけで
- 前方参照もしていない auto_ptr を宣言しているのは何故?
- テンプレート引数 _Ty は使用しない?(テンプレートじゃない?)
このクラス(テンプレート?)自体は,auto_ptr 同士を代入演算子で転送するときのためのものと思うのですが,実装のレベルや今回のポインタ代入の問題を見ると,どうにも失敗作としか思えません。
もう少し完成度の高い Smart Pointer が一般的に使えるようになるまでは,
- 初期化はコンストラクタ引数で行う
- auto_ptr 同士の代入などは行わない
追記:
やっぱり同じ内容で悩んでいる人はいるものですね。ご苦労さまです:
http://www.velocityreviews.com/forums/t458584-autoptr-assignment-crash-with-vc-language-extensions.html