ぼく用あれこれまとめ

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のスマートポインタのスライドだけど参考になるかと。
記事メニュー
目安箱バナー