unique_ptrを使った暗黙裏でのオブジェクト解体(C++11以上向け)

こんにちは、前回のSTLの記事を書いても余り意味は無いと思ったので、題名の通りのやつを書きます。

よく、C++のdelete忘れが多くなってきたこの頃、スマートポインタさんを使って、
一定のスコープから抜け出す時、オブジェクト解体をプログラムさんに裏でやらせようと言う魂胆です。

では、まず以下の様なクラスがあるとして、

1
2
3
4
5
6
7
8
9
10
//可読性的な問題でusing namespace std;
//猫のオブジェクト
class ClassNeko{
public:
ClassNeko(string n):voice{n}{} //コンストラクタ
~ClassNeko(){}; //ディストラクタ
void sakebu(){cout << voice << endl;}
private:
string voice;
};

こいつを使う以下の関数を定義したとします。

1
2
3
4
5
6
7
8
void nekoPlay(){
vector<ClassNeko*> neko; //猫のオブジェクトを作るコンテナ(可変配列のようなもの)作成。
//0-1の番号をしゃべる猫のオブジェクト作成
for(int i = 0;i < 5;i++)neko.push_back(new ClassNeko{to_string(i)});
for(int i = 0;i < 5;i++)neko[i]->sakebu();//順に鳴かせる
}

さて、この関数の問題としては、関数内で動的確保して使われた猫のオブジェクトを開放(delete)してないことです。
たとえvectorがするにしても、もし自作のコンテナを使ったとして、
その自作のコンテナが開放作業をしない(ユーザーに任せる)仕様だったらどうでしょう?
猫のデータは、メモリ領域に留まったままだとメモリリークを起こします。

では、どうすればいいでしょう。
普通は以下のようにやりますが、

1
2
//nekoPlay()関数内
for(auto x:v)delete v;

これだと、型の違うオブジェクトをたくさん作ったらたくさん書かないといけないから、
余計行が多くなりますし、そもそもdelete自体忘れるのもありますね。

ここで、スマートポインタさんを使います。

変更は、nekoPlay()内です。

1
2
3
4
5
6
7
8
void nekoPlay(){
//猫のオブジェクトのスマートポインタを作るコンテナ(可変配列のようなもの)作成。
vector<unique_ptr<ClassNeko>> neko;
//0-1の番号をしゃべる猫のオブジェクト(unique_ptr<ClassNeko>にキャスト)作成
for(int i = 0;i < 5;i++)neko.push_back(unique_ptr<ClassNeko>{new ClassNeko{to_string(i)}});
for(int i = 0;i < 5;i++)neko[i]->sakebu();//順に鳴かせる
}//スコープから抜けだしたので、猫オブジェクトは暗黙裏で解体。

ちょっと宣言等が長くなりましたが、どうでしょう。
delete忘れに最適ですね。でも宣言なげえ。