auto_ptr和unique_ptr
auto_ptr
和 unique_ptr
都是独占所有权的智能指针,但 unique_ptr
更加安全、灵活。
1. auto_ptr
(C++98产生)
特点
-
独占所有权:同一时间只能有一个
auto_ptr
管理对象。 -
转移语义:拷贝或赋值时会转移所有权(原指针变为
nullptr
)。 -
不推荐使用:由于不安全的拷贝行为,C++11 起被废弃,C++17 移除。
底层实现(简化版)
cpp
template<typename T> class auto_ptr { private:T* ptr;public:explicit auto_ptr(T* p = nullptr) : ptr(p) {}~auto_ptr() { delete ptr; }// 拷贝构造函数(转移所有权)auto_ptr(auto_ptr& other) : ptr(other.release()) {}// 赋值操作(转移所有权)auto_ptr& operator=(auto_ptr& other) {if (this != &other) {delete ptr; // 释放当前资源ptr = other.release(); // 接管 other 的资源}return *this;}// 释放所有权(返回原始指针,并置空)T* release() {T* temp = ptr;ptr = nullptr;return temp;}// 获取指针T* get() const { return ptr; }// 解引用T& operator*() const { return *ptr; }T* operator->() const { return ptr; } };
问题
-
拷贝时会静默转移所有权:
cpp
auto_ptr<int> p1(new int(42)); auto_ptr<int> p2 = p1; // p1 变成 nullptr,p2 接管资源1.容易导致意外的悬空智能指针。
-
不能用于 STL 容器(因为容器要求元素可拷贝,但
auto_ptr
的拷贝会改变原对象)。 -
不支持自定义删除器。
2. unique_ptr
(C++11 引入,推荐使用)
特点
-
独占所有权(和
auto_ptr
一样)。 -
禁止拷贝(但支持移动语义
std::move
)。 -
支持自定义删除器(可用于管理
FILE*
、malloc
内存等)。 -
可用于 STL 容器(因为支持移动语义)。
底层实现(简化版)
cpp
template<typename T, typename Deleter = std::default_delete<T>> class unique_ptr { private:T* ptr;Deleter deleter;public:explicit unique_ptr(T* p = nullptr) : ptr(p) {}~unique_ptr() {if (ptr) deleter(ptr);}// 禁止拷贝unique_ptr(const unique_ptr&) = delete;unique_ptr& operator=(const unique_ptr&) = delete;// 支持移动构造unique_ptr(unique_ptr&& other) noexcept : ptr(other.release()), deleter(std::move(other.deleter)) {}// 支持移动赋值unique_ptr& operator=(unique_ptr&& other) noexcept {if (this != &other) {reset(other.release());deleter = std::move(other.deleter);}return *this;}// 释放所有权T* release() {T* temp = ptr;ptr = nullptr;return temp;}// 重置指针(先删除旧资源)void reset(T* p = nullptr) {if (ptr) deleter(ptr);ptr = p;}// 获取指针T* get() const { return ptr; }// 解引用T& operator*() const { return *ptr; }T* operator->() const { return ptr; } };
优点
-
更安全:
-
禁止拷贝,避免
auto_ptr
的静默所有权转移问题。 -
必须显式使用
std::move
转移所有权:cpp
unique_ptr<int> p1(new int(42)); unique_ptr<int> p2 = std::move(p1); // p1 变为 nullptr
-
-
支持自定义删除器:
cpp
auto file_deleter = [](FILE* f) { if (f) fclose(f); }; unique_ptr<FILE, decltype(file_deleter)> file_ptr(fopen("test.txt", "r"), file_deleter);
-
可用于 STL 容器:
cpp
vector<unique_ptr<int>> vec; vec.push_back(unique_ptr<int>(new int(10)));