C++には、ガベージコレクションがないので、newで確保したメモリはdeleteで解放しなければならない・・・。
しかし、大きなプログラムになるとdeleteし忘れることもあるだろう・・・。
そのような場合に備えて、C++ではスマートポインタなるものがある・・・。
これは自動でメモリを解放してくれる便利な仕組みなのだが、使い方や特徴に注意しないといけない部分もある・・・。
まずは、auto_ptrについて・・・。
(※.ただし、このauto_ptrはC++11で非推奨になったので、使わないこと!)
(※.このように"deprecated"されているのでC++11以降では使えない・・・。)
まずtest.hは、
auto_ptrを使うにはmemoryをインクルードする・・・。
class_testはint型のx_をメンバに持つクラス・・・。
コンストラクタ、またはメンバ関数setでセットされ、getで取得でき、printで出力をする・・・。
また、std::auto_ptr
test.cppで、コンストラクタで呼ばれたこととx_にセットされた値、デストラクタで呼ばれたこととx_にセットされていた値を出力するようにしている・・・。
set, get, printはこの通り、セット、取得、出力である・・・。
funcでは引数のauto_ptrであるpのprintでx_を出力、そのあとsetで30をセットして、returnでp返している・・・。
(引数も戻り値も参照ではないのでコピーが発生する・・・。)
main関数では、
newでclass_testオブジェクトを生成し、コンストラクタ引数に10をセット・・・。
これを普通のポインタに格納しておくのではなく、std::auto_ptr
newしたのだから、deleteをしないといけないはずだが、auto_ptrに渡した場合はこれでいい・・・。deleteする必要が無いからだ・・・。
newしたオブジェクトはauto_ptrに渡ったら、所有権がauto_ptr側に移るので、以降auto_ptrのp1が管理する・・・。
そしてauto_ptrはコピーが発生するたびに所有権がコピー先に移っていくので、コピー元には残らない・・・。
(移動、または破壊的コピー)
p1->printで値を出力・・・。
p1->setで20をセット・・・。
p1をp2に代入・・・。
コピーなので所有権の移動が発生・・・。
以降p1はNULLとなり使えなくなる・・・。
p2->printで値を出力・・・。
そのあとにp1->printを試してみたら、
$ ./main class_test::class_test(10) x_ = 10 x_ = 20 Segmentation fault $
となるので、p1がNULLなのがわかる・・・。
p2をfuncに渡してp3で受け取る・・・。
p2→funcのp→p3という感じで2段階の移動が発生・・・。
p2はもう使えない・・・。
p3->printで出力・・・。
p2->printを呼ぶと、
$ vi main.cpp $ g++ -o main main.cpp test.cpp $ ./main class_test::class_test(10) x_ = 10 x_ = 20 x_ = 20 x_ = 30 Segmentation fault $
となる・・・。
呼ばなければ、
$ vi main.cpp $ g++ -o main main.cpp test.cpp $ ./main class_test::class_test(10) x_ = 10 x_ = 20 x_ = 20 x_ = 30 class_test::~class_test() x_ = 30 $
こうなる・・・。
最初にnewでp1に渡したclass_testオブジェクトのメモリはp3まで続き、p3->printを呼んで、p3がスコープを抜けるときにデストラクタが発生する・・・。
しかし、このauto_ptrはいろいろ問題点があり、C++11で非推奨となったので、くれぐれも使わないこと!
Sample/cpp/auto_ptr/auto_ptr/src/auto_ptr at master · bg1bgst333/Sample · GitHub