auto_ptr?auto_ptr 是 C++98 標準庫提供的智慧指標類別模板(定義於 <memory>),用於自動管理單一動態配置物件的生命週期。當 auto_ptr 物件離開作用域(生命週期結束)時,其建構函式會自動呼叫 delete 釋放所擁有的記憶體,避免記憶體洩漏。
重要限制:auto_ptr不支援陣列(new Type[]),若用於管理陣列會導致未定義行為。C++11 起已棄用,改由unique_ptr、shared_ptr取代。
#include <memory>
#include <string>
using namespace std;
// 1. 直接以 new 運算式初始化
auto_ptr<int> pi(new int(1024));
if (*pi != 1024) { /* ... */ }
// 2. 管理類別物件(如 string)
auto_ptr<string> pstr(new string("Hello world"));
pstr->size(); // 像普通指標一樣透過 -> 存取成員
// 3. 預設建構(內部指標為 null)
auto_ptr<int> p_null;
// 必須先 reset() 才能使用
p_null.reset(new int(42));
auto_ptr 最大的特點是嚴格的所有權語意:同一時間只能有一個 auto_ptr 擁有某個物件。複製建構或指派時,所有權會從來源轉移給目標,來源變為空(null)。
auto_ptr<string> p1(new string("Hello"));
auto_ptr<string> p2(p1); // 複製建構:p2 取得所有權,p1 變空
// p1.get() == 0, p2.get() 指向 "Hello"
auto_ptr<int> q1(new int(10));
auto_ptr<int> q2(new int(20));
q1 = q2; // 指派:先刪除 q1 原本擁有的 10,再轉移 q2 所有權給 q1
// q1 指向 20,q2 變空
這機制避免了「雙重釋放」錯誤,但也意味著 auto_ptr 不可存放於標準容器(如 vector<auto_ptr<T>>),因為容器操作會觸發複製導致所有權錯亂。
| 函式 | 說明 |
|---|---|
get() | 取得內部原始指標(不轉移所有權)。 |
release() | 釋放所有權並回傳原始指標,auto_ptr 變空。 |
reset(ptr = 0) | 重新指向新物件;若原本擁有物件則先 delete。 |
operator* / operator-> | 解參考與成員存取,行為同原始指標。 |
release() 與 get() 的關鍵差異auto_ptr<string> p1(new string("HELLO"));
auto_ptr<string> p2(p1.get()); // 錯誤!雙重擁有同一物件 → 雙重 delete
auto_ptr<string> p3(p1.release()); // 正確!所有權轉移給 p3,p1 變空
若需重複使用同一 auto_ptr 管理的字串物件,優先使用 assign() 而非 reset(new string(...)):
auto_ptr<string> p(new string("Hello World"));
p->assign("YES"); // 高效:重用記憶體,避免 delete/new 開銷
// p.reset(new string("YES")); // 較慢:釋放舊物件再配置新物件
new 配置的記憶體(如堆疊物件、malloc 記憶體),否則 delete 導致未定義行為。auto_ptr 共享同一物件(除非透過 release() 明確轉移)。delete[] 不會被呼叫)。C++11 起請改用:
std::unique_ptr:獨占所有權,可移動不可複製,支援陣列(unique_ptr<T[]>),零開銷。std::shared_ptr:共享所有權,參考計數,執行期稍有開銷。std::weak_ptr:輔助 shared_ptr 打破循環參考。// 現代寫法範例
#include <memory>
#include <string>
unique_ptr<string> up(new string("Modern C++"));
// unique_ptr 不可複製,但可移動
unique_ptr<string> up2 = std::move(up); // 所有權轉移
auto_ptr 是早期 C++ 智慧指標的先驅,雖已棄用,但其所有權轉移概念深刻影響了後來的 unique_ptr 設計。理解 auto_ptr 的行為有助於閱讀舊代碼庫,並在遷移至現代 C++ 時做出正確選擇。