c++如何实现一个简单的智能指针_c++手写unique_ptr理解RAII

1次阅读

实现简化版unique_ptr需遵循RaiI原则,通过构造获取资源、析构释放资源,禁止拷贝、支持移动语义,确保独占所有权,利用操作符重载提供指针行为,自动管理内存防止泄漏。

c++如何实现一个简单的智能指针_c++手写unique_ptr理解RAII

实现一个简单的智能指针,尤其是模仿 unique_ptr,是理解 c++ 中 RAII(Resource Acquisition Is Initialization)机制的绝佳方式。RAII 的核心思想是:资源的生命周期由对象的生命周期自动管理——构造时获取资源,析构时释放资源。

下面通过手写一个简化版的 unique_ptr 来说明其原理和实现方式。

1. 简化版 unique_ptr 的基本结构

我们希望这个智能指针:

  • 独占所管理的对象,不能被复制。
  • 可以移动(move),转移所有权。
  • 在析构时自动 delete 所指对象。
  • 支持解引用和成员访问操作符。

template<typename T> class UniquePtr { private: T* ptr_;  // 原始指针</p><p>public: // 构造函数:接收裸指针 explicit UniquePtr(T* p = nullptr) : ptr_(p) {}</p><pre class='brush:php;toolbar:false;'>// 析构函数:释放资源,体现 RAII ~UniquePtr() {     delete ptr_; }  // 禁止拷贝构造和拷贝赋值 UniquePtr(const UniquePtr&) = delete; UniquePtr& operator=(const UniquePtr&) = delete;  // 移动构造 UniquePtr(UniquePtr&& other) noexcept : ptr_(other.ptr_) {     other.ptr_ = nullptr;  // 转移所有权 }  // 移动赋值 UniquePtr& operator=(UniquePtr&& other) noexcept {     if (this != &other) {         delete ptr_;       // 释放当前资源         ptr_ = other.ptr_; // 接收所有权         other.ptr_ = nullptr;     }     return *this; }  // 解引用 T& operator*() const {     return *ptr_; }  // 成员访问 T* operator->() const {     return ptr_; }  // 获取原始指针(不转移) T* get() const {     return ptr_; }  // 释放所有权,返回原始指针 T* release() {     T* temp = ptr_;     ptr_ = nullptr;     return temp; }  // 重置内部指针 void reset(T* p = nullptr) {     delete ptr_;     ptr_ = p; }

};

立即学习C++免费学习笔记(深入)”;

2. 使用示例

测试我们实现的 UniquePtr

</p>                     <div class="aritcle_card">                         <a class="aritcle_card_img" href="/ai/1242">                             <img src="https://img.php.cn/upload/ai_manual/001/431/639/68b79c659820e469.png" alt="Stable Diffusion 2.1 Demo">                         </a>                         <div class="aritcle_card_info">                             <a href="/ai/1242">Stable Diffusion 2.1 Demo</a>                             <p>最新体验版 Stable Diffusion 2.1</p>                             <div class="">                                 <img src="/static/images/card_xiazai.png" alt="Stable Diffusion 2.1 Demo">                                 <span>136</span>                             </div>                         </div>                         <a href="/ai/1242" class="aritcle_card_btn">                             <span>查看详情</span>                             <img src="/static/images/cardxiayige-3.png" alt="Stable Diffusion 2.1 Demo">                         </a>                     </div>                 <h1>include <iostream></h1><p>struct MyClass { int value; MyClass(int v) : value(v) { std::cout << "MyClass(" << value << ") constructedn"; } ~MyClass() { std::cout << "MyClass(" << value << ") destructedn"; } };</p><p>int main() { { UniquePtr<MyClass> ptr(new MyClass(42)); std::cout << "Value: " << ptr->value << "n";</p><pre class='brush:php;toolbar:false;'>    // ptr2 = ptr; // 编译错误:禁止拷贝     UniquePtr<MyClass> ptr2 = std::move(ptr); // 合法:移动     // 此时 ptr 为空,ptr2 拥有对象 } // 自动调用析构,释放资源 return 0;

}

输出会显示构造和析构过程,证明资源被正确管理。

3. RAII 的体现

RAII 的关键在于“资源即对象”:

  • 构造函数中获取资源(如 new)。
  • 析构函数中释放资源(如 delete)。
  • 只要对象在上,离开作用域就会自动析构,从而确保资源不泄漏。

我们的 UniquePtr 把动态内存包装成一个局部对象,无需手动调用 delete,极大降低出错概率。

4. 关键点总结

  • 独占语义:通过删除拷贝操作,保证同一时间只有一个智能指针拥有资源。
  • 移动语义:使用右值引用实现安全的所有权转移。
  • 自动清理:析构函数中 delete 是 RAII 的核心。
  • 操作符重载:让智能指针像普通指针一样使用。

基本上就这些。实现一个简易 unique_ptr 不复杂但容易忽略细节,比如移动赋值中的自赋值检查和资源释放顺序。掌握它有助于深入理解现代 C++ 的资源管理哲学。

text=ZqhQzanResources