初めに
Rustのメモリ管理を勉強する中で、C++のスマートポインタと混同してきたので、学びなおした。
unique_ptr
概要
- C++11~
- ライブラリ
<memory>
あるメモリの所有者が一つであることを保証する。
特徴
- コピー不可(コピーコンストラクタ削除)
- ムーブ可能(所有権の移動ができる)
- スコープ終了とともに自動で
delete - コストは生ポインタと同じくらい軽い(オーバーヘッドがゼロに近い)
使用例
#include <memory>
#include <iostream>
int main() {
std::unique_ptr<int> p = std::make_unique<int>(10);//メモリ確保
std::cout << *p << std::endl;
// 所有権の移動
std::unique_ptr<int> q = std::move(p);
//`p`は空になる
if (!p) std::cout << "p is now empty" << std::endl;
return 0;
}
出力
10
p is now empty
Rustとの違い
C++のスマートポインタはクラスであり言語仕様ではない。
言語仕様としてメモリの安全性を重視しているRustよりは安全性が低い。
具体的には
1. 所有権の仕組みそのものが違う
C++ (unique_ptr)
- コピー禁止
Rust
- 言語レベルで所有権を強制する
- 借用規則(
mutable/immutable)、ライフタイム、
すべてコンパイル時にチェック
2. ムーブの違い
C++ (unique_ptr)
- std::move を呼ぶ必要がある
-
moveは実際にはキャストであり、移動の意図をコンパイラに伝えるだけ
Rust
- 代入した時点で勝手にムーブ
- 所有権の移動は 言語仕様に組み込み
3. 借用(参照)の安全性が違う
C++ (unique_ptr + 生ポインタ)
- 借用の概念は「開発者が守るもの」
-
&で参照しても、同時に可変参照を作れてしまう - ライフタイムの概念はコンパイラに存在しない
Rust
- 不変参照は複数可
- 可変参照は 1 つだけ
- ライフタイムがすべて追跡される
- ダングリングは原理的にコンパイルエラー
4. Dropの違い
C++
- RAII
- スコープを抜けると
unique_ptrのデストラクタが呼ばれdelete
Rust
- RAII(ほぼ同じ概念)
- Dropトレイトで制御可能
- 生ポインタは存在するが
unsafeブロック外では使えない
終わりに
Rust難しい
~Thank you for reading~