ぼく用あれこれまとめ
std::auto_ptr
最終更新:
bokuyo
-
view
std::auto_ptr
- C++ってnewしたあとにdeleteしないといけないとか面倒だよね。
- deleteし忘れるとメモリリーク起こるし…。
- そこで使うのがガベージコレクション、またの名をスマートポインタなの。
- C++の標準ライブラリにはstd::auto_ptrっていうスマートポインタが実装されてるの!
auto_ptrの特徴?
- スコープを外れるとdeleteしてくれる。
- 所有権という考え方。
- 所有権は常に1人しか持てないとか面倒すぎる。
- こんなの使えないよぉ…って人は<boost/shared_ptr.hpp>を使うといいかも。
- STLとauto_ptrの組み合わせって結構相性悪いから、そういうときはboost::shared_ptrを使うといいよ。
使い方。
#include <iostream> #include <memory> class Eureka { public: ~Eureka(){ std::cout << "Seven" << std::endl; }; }; void seven() { std::auto_ptr<Eureka> p(new Eureka()); } int main() { seven(); return 0; }
- <memory>をincludeしてあげてね。
- seven()関数を抜けると、デストラクタが勝手に発動する。つまり自動的にdeleteされるの。
- 普通にnewしたときと同じように「p->」でメンバ変数/メソッドにアクセスできるの。
Eureka* eureka = new Eureka(); std::auto_ptr<Eureka> p(eureka);
- こう書いてもおk。
危険な使い方。
class Eureka { public: ~Eureka(){ std::cout << this << std::endl; }; }; void seven() { Eureka* eureka = new Eureka(); std::auto_ptr<Eureka> renton(eureka); std::auto_ptr<Eureka> holland(eureka); std::auto_ptr<Eureka> nirvash(eureka); }
- 複数のstd::auto_ptrで、同じeurekaを指すと大変なことになります。
- eurekaの所有権は常に1人しかもっちゃいけない約束なのです。
所有権を移す。
#include <iostream> #include <memory> class Eureka { public: ~Eureka(){ std::cout << this << std::endl; }; }; std::auto_ptr<Eureka> seven() { std::auto_ptr<Eureka> p(new Eureka()); return p; } void renton() { std::cout << "アバンストラッシュ!" << std::endl; std::auto_ptr<Eureka> unco = seven(); } int main() { renton(); return 0; }
- seven()内で確保したeurekaの所有権は、auto_ptrのpが持ってる。
- seven()を抜けるとdeleteされるかとおもえば、renton内のuncoに戻り値として所有権を渡してる。
- renton()を抜けるとdeleteされる。
関数の引数として渡しちゃう。
void Apprivoiser(Eureka* ptr) { return; } int main() { std::auto_ptr<Eureka> eureka(new Eureka()); Apprivoiser(eureka.get()); //Apprivoiser(eureka);はコンパイルエラー return 0; }
- 「eureka.get()」のように、.get()メソッドを使ってパラメータに渡す。
- じゃあ、もし、パラメータに「eureka」を渡したら?どうなるの?
class Eureka { public: ~Eureka(){ std::cout << this << std::endl; }; }; void Apprivoiser(std::auto_ptr<Eureka> ptr) { return; } int main() { std::auto_ptr<Eureka> eureka(new Eureka()); Apprivoiser(eureka); std::cout << "綺羅星" << std::endl; return 0; }
- パラメータに「std::auto_ptr<>」をそのまま使うと、Apprivoiser()内でptrが使える。
- だけど、このとき所有権はApprivoiser()内のptrにあるので、Apprivoiser()のスコープから抜けるとdeleteされちゃう。
- Apprivoiser()から抜けたmain()関数内のeurekaはもう解放されちゃって何も持ってない。
- だからなるべく、get()メソッド使う形にしてね。
参考文献
- shared_ptr & weak_ptr (pdf 第2版) - 所有ってどう考えればいいの?って人にお勧め。boostのスマートポインタのスライドだけど参考になるかと。