🌟
C++スマートポインタ入門
スマートポインタとは
スマートポインタはC++の機能であり、動的なメモリ管理を簡単に行うために使用されます。従来のポインタと比べて、メモリリークや二重解法のリスクを減らし、プログラムの安全性を向上させます。
new/deleteでの目盛り管理の課題点
- メモリリークの可能性
- delete漏れ:
new
で確保したメモリに対して、適切なタイミングでdelete
を行わなかった場合、メモリリークが発生します。例えば、関数内でオブジェクトをnew
して返し、呼び出し元で忘れてしまうなど
- delete漏れ:
- 二重解放の可能性
- 同じメモリを複数のポインターが所有している場合、それらのポインタが別々のタイミングで
delete
を呼び出すと、同じメモリが二重解放される。二回目の解放ではその番地を他の変数が使用している可能性があり、メモリ破壊を引き起こす
- 同じメモリを複数のポインターが所有している場合、それらのポインタが別々のタイミングで
これらの課題はスマートポインターの導入によって解決できます。
C++20スマートポインタの種類
-
unique_ptr
- 単一の所有権を持つスマートポインタ。所有権の移譲により、一つの
unique_ptr
から別のunique_ptr
に移すことが可能。 - 所有権を持つのは常に一つの
unique_ptr
であり、複数のunique_ptr
間で共有することはできない
- 単一の所有権を持つスマートポインタ。所有権の移譲により、一つの
-
shared_ptr
- 共有の所有権を持つスマートポインタ。複数の
shared_ptr
が同じオブジェクトを所有することが可能。 - 所有権のカウントが0になると、自動的にメモリの開放が行われる
- 循環参照を防ぐために、
weak_ptr
と組み合わせて使用することができる
- 共有の所有権を持つスマートポインタ。複数の
-
weak_ptr
- 非所有権の観察用ポインタ。
shared_ptr
と組み合わせて使用され、所有権を持たない状態でオブジェクトにアクセスることが可能。 -
weak_ptr
は、オブジェクトの寿命に関与せず、循環参照を防ぐために使用される。
- 非所有権の観察用ポインタ。
スマートポインターの比較
種類 | 所有権 | コピー | ムーブ | 特徴 |
---|---|---|---|---|
unique_ptr | 単独 | × | 〇 | 所有権の独占、効率的なリソース管理 |
shared_ptr | 共有 | 〇 | 〇 | 参照カウントによる共有、循環参照対策 |
weak_ptr | - | × | 〇 |
shared_ptr との親和性、循環参照対策 |
使いどころとサンプルコード
- unique_ptrのサンプル
#include <memory>
#include <iostream>
class Robot {
public:
void greet() {
std::cout << "こんにちは!私はロボットです。" << std::endl;
}
};
int main() {
// ロボットオブジェクトの所有権をunique_ptrで管理します
std::unique_ptr<Robot> robotPtr(new Robot());
// ロボットオブジェクトへの所有権を別のunique_ptrに移譲します
std::unique_ptr<Robot> anotherRobotPtr = std::move(robotPtr);
// 移譲されたロボットオブジェクトに挨拶させます
anotherRobotPtr->greet();
return 0;
}
- ロボットオブジェクトの所有権を
unique_ptr
で管理 -
unique_ptr
を使って所有権の移譲を行う - 移譲されたロボットオブジェクトに対して挨拶させる
- shared_ptrのサンプル
#include <memory>
#include <iostream>
class Robot {
public:
void dance() {
std::cout << "踊ります!" << std::endl;
}
};
int main() {
// ロボットオブジェクトの所有権をshared_ptrで共有します
std::shared_ptr<Robot> robotPtr1 = std::make_shared<Robot>();
std::shared_ptr<Robot> robotPtr2 = robotPtr1; // 所有権の共有
// 共有されたロボットオブジェクトに対して踊りを指示します
robotPtr1->dance();
robotPtr2->dance();
return 0;
}
- ロボットオブジェクトの所有権を
shared_ptr
で共有 -
shared_ptr
を使って所有権を共有し、複数のshared_ptr
が同じロボットオブジェクトを参照 - 共有されたロボットオブジェクトに対して踊りを指示
- weak_ptrのサンプル
-
weak_ptr
はオブジェクトへの観察用ポインタとして使用されるため、循環参照を防ぐ場合に適しています。
-
#include <memory>
struct Node {
std::weak_ptr<Node> parent;
};
int main() {
std::shared_ptr<Node> parentNode = std::make_shared<Node>();
std::shared_ptr<Node> childNode = std::make_shared<Node>();
// 循環参照を防ぐため、weak_ptrを使用して親ノードを観察する
parentNode->child = childNode;
childNode->parent = parentNode;
return 0
まとめ
この記事では、スマートポインタの種類と特徴についてまとめ、それぞれのサンプルコードについて説明しました。
なお、C++20以降ではさらに改善されたスマートポインターの機能や追加された新機能もありますので、最新のC++リファレンスやドキュメントを確認してください。
cppリファレンス
スマートポインタを使って効率的で安全なコーディングをお楽しみください!
Discussion