正しいデストラクターを呼び出せますか?
//"sample01.cpp" #include <stdio.h> #include <stdlib.h> #include <new> #include <memory> class Foo; Foo *createFoo(); int main(int argc, char* argv[]) { Foo * f = createFoo(); delete f; return 0; }
//"sample02.cpp" #include<stdio.h> class Foo { public: Foo() { fprintf(stdout, "ctor.\n"); } ~Foo() { fprintf(stdout, "dtor.\n"); } }; Foo *createFoo() { return new Foo(); }
上のような感じのプログラムを書いて、いやな目にあった。上のコードだとFooのデストラクターは呼び出されない。リソースの後始末の処理とかデストラクターでしてたんだけど、それが行われなかったわけやね。
VC++(2005)は"sample01.cpp"をビルドすると警告を出すんだけど……(C4150)。他の警告に埋もれて、見落としていた。
上のコードだと、 delete が、どうオブジェクトを扱えばいいのかコンパイル時にわからんわけで、まあ、そりゃあかんのだろう。
もうすこし警告に気をつけろ……と。
そして、C++の仕様とか、もっと勉強せえってことだね……。
ちなみに"sample01.cpp"を"-Wall"オプションをつけて、g++でコンパイルしてみたら、g++も警告を出す(g++ 4.5.2)。警告のメッセージ自体が結構詳しい内容で、なるほどねーとか思った。
ただ、
//"sample01b.cpp" #include <stdio.h> #include <stdlib.h> #include <new> #include <memory> class Foo; Foo *createFoo(); int main(int argc, char* argv[]) { std::auto_ptr<Foo> f(createFoo()); f.reset(); return 0; }
ってなものにすると、g++は"sample01b.cpp"に対して何も警告を出さなかったりする。……恐ろしい。VC++ 2005は警告を出した。コンパイラーによって、得意不得意がいろいろあるね。
Pimplイディオム
こういうの、Pimplイディオムっていうらしいけど(名称、知らなかった)、自分が書いたのは、Pimplイディオムの悪い書き方だと思う。つか、Fooを破棄する処理は、いつもなら"sample02.cpp"の側に書いて、"sample01.cpp"からその処理を呼ぶようにするんだけど……。今回はうっかりそう書かなかった。そしてほげった。ははは……。
余談
まどマギのタイトル改変してみたけど、あまり上手にできてないなぁ。