std::unique_ptr是c++++11引入的智能指針,用于實現獨占式所有權的資源管理。其核心用途是確保某個資源只能被一個指針擁有,并在離開作用域時自動釋放,避免內存泄漏;“獨占式”意味著資源不能被復制,但可以通過移動語義轉移所有權;創建方式包括使用new直接初始化、推薦的std::make_unique以及管理數組類型的帶[]刪除器形式;訪問資源可通過*和->操作符進行;所有權轉移通過std::move實現,轉移后原指針為空;常見注意事項包括不要手動delete資源、可安全放入容器中使用、支持自定義刪除器以管理非內存資源。
std::unique_ptr 是 c++11 引入的一種智能指針,用來管理動態分配的對象,它的核心用途是實現獨占式所有權的資源管理。說白了,就是確保某個資源(通常是堆內存)只能被一個指針擁有,并在它不再需要時自動釋放,避免內存泄漏。
什么是“獨占式”?
“獨占式”意味著 std::unique_ptr 所指向的對象不能被復制給另一個 unique_ptr。也就是說,你不能寫這樣的代碼:
std::unique_ptr<int> p1(new int(5)); std::unique_ptr<int> p2 = p1; // 編譯錯誤!
這和 std::shared_ptr 不一樣,后者允許多個指針共享同一個對象的所有權。而 unique_ptr 的設計目的就是為了更明確地表達:這個資源只能有一個主人,誰離開作用域誰就負責釋放。
立即學習“C++免費學習筆記(深入)”;
怎么創建和使用 std::unique_ptr?
常見的用法其實很簡單,一般有以下幾種方式:
-
使用 new 直接初始化:
std::unique_ptr<int> ptr(new int(10));
-
使用 std::make_unique(推薦):
auto ptr = std::make_unique<int>(10);
這種方式更安全,也更簡潔,推薦優先使用。
-
管理數組類型(注意要用帶 [] 的刪除器):
auto arr = std::make_unique<int[]>(5); // 創建長度為5的int數組
訪問內部對象也很簡單,就像普通指針一樣用 * 和 -> 操作符:
auto user = std::make_unique<User>("Alice"); std::cout << user->getName() << std::endl;
如何轉移所有權?
雖然 unique_ptr 不支持拷貝,但可以移動(move)。比如你可以把它作為函數返回值或者參數傳遞出去:
std::unique_ptr<int> createInt() { return std::make_unique<int>(42); } void useInt(std::unique_ptr<int> ptr) { std::cout << *ptr << std::endl; }
調用方式如下:
auto p = createInt(); // 所有權從函數內轉移到p useInt(std::move(p)); // 轉移后,p變成空指針
注意:一旦移動之后,原來的指針就不再擁有資源了,相當于 NULL。
常見注意事項
-
不要手動 delete:用了 unique_ptr 就不需要也不應該手動調用 delete。
-
配合容器使用沒問題:可以把 unique_ptr 放進 std::vector 或 std::map 中,只要不涉及拷貝操作就行。
-
自定義刪除器(高級用法):如果你管理的不是普通 new 出來的內存,比如文件句柄、socket 等資源,可以通過模板指定自定義刪除邏輯。
struct MyDeleter { void operator()(FILE* fp) const { fclose(fp); } }; std::unique_ptr<FILE, MyDeleter> fp(fopen("file.txt", "r"));
基本上就這些。理解起來不難,但確實很容易因為習慣寫法而出錯,特別是剛從裸指針轉過來的時候。用多了你會發現,std::unique_ptr 不僅能幫你省去手動管理內存的麻煩,還能讓代碼結構更清晰。