読者です 読者をやめる 読者になる 読者になる

auto_ptr

C++には、ガベージコレクションがないので、newで確保したメモリはdeleteで解放しなければならない・・・。
しかし、大きなプログラムになるとdeleteし忘れることもあるだろう・・・。

そのような場合に備えて、C++ではスマートポインタなるものがある・・・。
これは自動でメモリを解放してくれる便利な仕組みなのだが、使い方や特徴に注意しないといけない部分もある・・・。

まずは、auto_ptrについて・・・。
(※.ただし、このauto_ptrはC++11で非推奨になったので、使わないこと!)

auto_ptr - C++ Reference

(※.このように"deprecated"されているのでC++11以降では使えない・・・。)

まずtest.hは、

auto_ptrを使うにはmemoryをインクルードする・・・。
class_testはint型のx_をメンバに持つクラス・・・。
コンストラクタ、またはメンバ関数setでセットされ、getで取得でき、printで出力をする・・・。

また、std::auto_ptr型を引数と戻り値にとる関数funcも宣言しておく・・・。

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型のp1のコンストラクタ引数に渡す・・・。
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