スマートポインタとは
C++のスマートポインタは、動的メモリ管理を自動化するためのクラスです。
スマートポインタを使えば手動でメモリを解放する必要がなくなるため、メモリリークなどの問題を防ぎやすくなります。
スマートポインタを使用できるC++のバージョンはC++11以降です。C++11で標準ライブラリに以下の3つのスマートポインタが導入されました。
std::unique_ptr
std::unique_ptr
は、所有権の唯一性を保証するスマートポインタです。
あるstd::unique_ptr
が所有するオブジェクトは、そのstd::unique_ptr
以外のものからはアクセスできません。所有権を他のstd::unique_ptr
に移すことは可能ですが、コピーはできません。
std::shared_ptr
std::shared_ptr
は、複数のポインタが同じオブジェクトを共有できるスマートポインタです。shared_ptr
は内部に参照カウントを持っており、誰もそのオブジェクトを参照しなくなったときに自動的にメモリが解放されます。
std::weak_ptr
std::weak_ptr
は、std::shared_ptr
と一緒に使われるスマートポインタで、参照カウントに影響を与えない弱い参照を持つために使用されます。std::weak_ptr
は循環参照を防ぐために役立ちます。
実装例
さきほど紹介した3つのスマートポインタについて、簡単な実装例を紹介します。
std::unique_ptr
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass Constructor\n"; }
~MyClass() { std::cout << "MyClass Destructor\n"; }
};
int main() {
std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>();
// std::unique_ptr<MyClass> ptr2 = ptr1; // コンパイルエラー
std::unique_ptr<MyClass> ptr2 = std::move(ptr1); // 所有権を移す
return 0;
}
std::shared_ptr
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass Constructor\n"; }
~MyClass() { std::cout << "MyClass Destructor\n"; }
};
int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
{
std::shared_ptr<MyClass> ptr2 = ptr1; // 参照カウントが増える
} // ptr2がスコープを抜けると参照カウントが減る
return 0; // ptr1がスコープを抜けると参照カウントが0になり、メモリが解放される
}
std::weak_ptr
#include <memory>
#include <iostream>
class MyClass {
public:
std::shared_ptr<MyClass> ptr;
MyClass() { std::cout << "MyClass Constructor\n"; }
~MyClass() { std::cout << "MyClass Destructor\n"; }
};
int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::weak_ptr<MyClass> weakPtr = ptr1; // weak_ptrは参照カウントを増やさない
if (auto sharedPtr = weakPtr.lock()) { // 有効なshared_ptrが存在する場合にアクセス
std::cout << "Shared object is still alive\n";
}
return 0;
}
まとめ
この記事では、C++のスマートポインタを紹介しました。
スマートポインタを使うことでメモリ管理が容易になり、バグを減らすことができます。