C++11引入了智慧指標,它們是管理動態分配記憶體的強大工具。本文將詳細介紹兩種最常用的智慧指標: std::unique_ptr
和 std::shared_ptr
。
std::unique_ptr
概述
std::unique_ptr
是一種獨佔所有權的智慧指標。它確保一個物件只能被一個 unique_ptr
所擁有,這意味著不能複製 unique_ptr
,只能移動它。
主要特性
- 獨佔所有權: 一個
unique_ptr
不能被複制,只能被移動。 - 自動釋放: 當
unique_ptr
離開作用域時,它所管理的物件會被自動刪除。 - 零開銷: 在大多數操作中,
unique_ptr
與原始指標的效能相當。 - 自定義刪除器: 可以指定自定義的刪除方式。
示例程式碼
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "MyClass constructed\n"; }
~MyClass() { std::cout << "MyClass destructed\n"; }
void doSomething() { std::cout << "Doing something\n"; }
};
int main() {
// 建立unique_ptr
std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>();
// 使用->訪問成員
ptr1->doSomething();
// 無法複製unique_ptr
// std::unique_ptr<MyClass> ptr2 = ptr1; // 編譯錯誤
// 可以移動unique_ptr
std::unique_ptr<MyClass> ptr2 = std::move(ptr1);
// ptr1現在為空
if (ptr1 == nullptr) {
std::cout << "ptr1 is null\n";
}
// ptr2現在擁有物件
ptr2->doSomething();
// 離開作用域時,ptr2自動刪除物件
}
std::shared_ptr
概述
std::shared_ptr
是一種共享所有權的智慧指標。多個 shared_ptr
可以指向同一個物件,物件的記憶體會在最後一個引用被銷燬時釋放。
主要特性
- 共享所有權: 多個
shared_ptr
可以指向同一個物件。 - 引用計數: 內部維護一個引用計數,當計數降為0時刪除物件。
- 執行緒安全: 引用計數的增減是原子操作,但物件本身的訪問不是執行緒安全的。
- 可以從 this 指標建立: 可以安全地從一個物件的成員函式中建立指向 this 的
shared_ptr
。
示例程式碼
#include <iostream>
#include <memory>
class SharedClass : public std::enable_shared_from_this<SharedClass> {
public:
SharedClass() { std::cout << "SharedClass constructed\n"; }
~SharedClass() { std::cout << "SharedClass destructed\n"; }
std::shared_ptr<SharedClass> getShared() {
return shared_from_this();
}
};
int main() {
// 建立shared_ptr
auto ptr1 = std::make_shared<SharedClass>();
{
// 建立另一個指向同一物件的shared_ptr
std::shared_ptr<SharedClass> ptr2 = ptr1;
std::cout << "使用計數: " << ptr1.use_count() << std::endl; // 輸出 2
// 從物件內部獲取shared_ptr
auto ptr3 = ptr1->getShared();
std::cout << "使用計數: " << ptr1.use_count() << std::endl; // 輸出 3
// ptr2和ptr3離開作用域,但物件不會被刪除
}
std::cout << "使用計數: " << ptr1.use_count() << std::endl; // 輸出 1
// ptr1離開作用域,物件被刪除
}
比較 unique_ptr 和 shared_ptr
特性 | std::unique_ptr | std::shared_ptr |
---|---|---|
所有權 | 獨佔 | 共享 |
複製 | 不允許 | 允許 |
移動 | 允許 | 允許 |
引用計數 | 無 | 有 |
效能開銷 | 幾乎為零 | 有一定開銷 |
記憶體使用 | 與原始指標相同 | 額外記憶體用於控制塊 |
執行緒安全 | 不適用 | 引用計數操作是安全的 |
迴圈引用 | 不會發生 | 可能發生,需要注意 |
最佳實踐
- 優先使用
std::unique_ptr
,除非確實需要共享所有權。 - 使用
std::make_unique
和std::make_shared
來建立智慧指標。 - 避免使用裸指標,儘可能使用智慧指標。
- 注意避免
std::shared_ptr
的迴圈引用問題,必要時使用std::weak_ptr
。 - 在類的公共介面中返回
std::unique_ptr
來轉移所有權。 - 在需要共享但不參與所有權的場景中使用
std::weak_ptr
。
std::unique_ptr
和 std::shared_ptr
是C++中管理動態記憶體的強大工具。正確使用這些智慧指標可以大大減少記憶體洩漏的風險,提高程式碼的安全性和可維護性。理解它們的特性和適用場景對於編寫高質量的C++程式至關重要。