C++で動的メモリを使う場合new
やdelete
を使って管理しますが、メモリリークや二重解放といった問題が発生しやすくなります。
そこで、登場するのがC++11からの機能である「スマートポインタ」
スマートポインタは、特定のスコープから外れると自動的にメモリを解放してくれるため、メモリ管理の負担が軽減されます。
今回は、ポインタの所有権を唯一持っているように振る舞うunique_ptr
の使い方を紹介します。
unique_ptrの概要
unique_ptr
は、特定のリソースへのポインタの所有権を唯一持っているスマートポインタです。
所有権とは、「誰がそのメモリやリソースを管理しているか」という権利を指し、unique_ptr A
が持つオブジェクトに対する所有権は、unique_ptr A
にしか割り当てられないため、そのリソースを管理できるのはunique_ptr A
のみとなります。
unique_ptr
は、コピー不可なクラスとなっており、unique_ptr
を他の変数に代入することはできません。
その代わり、std::move
を使って、他のunique_ptr
へ所有権を譲渡することができます。
unique_ptrの使い方
unique_ptr
の使い方です。
#include <iostream>
#include <memory> // unique_ptrを使用するために必要
int main() {
// unique_ptrを作成する
std::unique_ptr<int> p(new int(100));
std::cout << *p << std::endl; // 出力値は100
// deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}
make_uniqueを使用してunique_ptrを作成する
C++14からはmake_unique
を使用可能。
#include <iostream>
#include <memory> // unique_ptrを使用するために必要
int main() {
// std::make_uniqueを使用してunique_ptrを作成する
std::unique_ptr<int> p = std::make_unique<int>(100);
std::cout << *p << std::endl; // 出力値は100
// deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}
p
というunique_ptr
が作られ、100
を保持しています。p
がスコープから抜ける(main関数から抜ける)とp
が指しているメモリが自動的に解放されます。
std::moveを使用して所有権を移動する
#include <iostream>
#include <memory> // unique_ptrを使用するために必要
int main() {
// std::make_uniqueを使用してunique_ptrを作成する
std::unique_ptr<int> p = std::make_unique<int>(100);
// 所有権の譲渡
std::unique_ptr<int> p2(std::move(p));
std::cout << *p2 << std::endl; // 出力値は100
// deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}
std::move
を使用して、unique_ptr p
の所有権をunique_ptr p2
へ譲渡しています。これによりp
は何も所有していない状態になります。
resetでリソースの解放
#include <iostream>
#include <memory> // unique_ptrを使用するために必要
int main() {
// std::make_uniqueを使用してunique_ptrを作成する
std::unique_ptr<int> p = std::make_unique<int>(100);
// リソースの解放
p.reset();
// リソースの再設定
p.reset(new int(10));
std::cout << *p << std::endl; // 出力値は10
// deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}
reset()
でリソースの解放ができます。reset
の引数に新たなリソースを指定すると、新たなリソースの所有権を設定できます。
unique_ptrまとめ
unique_ptr
はC++で使われるスマートポインタの一種で、一つのオブジェクトに対する所有権を一つだけ持ちます。
unique_ptr
には以下の様な特徴があります。
unique_ptrの特徴
- 所有権が一つだけ:
unique_ptr
は一つのリソースに対して、一つの所有権しか持たない - コピーができない:
unique_ptr
は他の変数に代入することはできない
もし2つのポインタが同じメモリを管理していた場合、どちらかがメモリを解放してしまうと、もう一方のポインタが使おうとしたときに既にメモリが解放されていてプログラムがクラッシュする可能性があります。
unique_ptr
はこのようなバグを防ぐために、一つのリソースは一つの所有者しか持たないというルールになっています。
その他のスマートポインタは、以下を参照してください。