欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > C++智能指针

C++智能指针

2025/6/23 13:21:40 来源:https://blog.csdn.net/2401_88413914/article/details/148828732  浏览:    关键词:C++智能指针

前言

智能指针是C++中用于自动化资源管理的对象,它封装了原始指针,并提供了自动内存管理的功能。智能指针的核心思想是RAII(Resource Acquisition Is Initialization),即在对象构造时获取资源,在对象析构时释放资源。

为什么需要智能指针

// 传统指针的问题示例
void problemDemo() {int* rawPtr = new int(10);  // 分配内存if (someCondition) {throw std::runtime_error("Error!");  // 抛出异常// 下面的delete不会被执行,导致内存泄漏}delete rawPtr;  // 手动释放内存
}

C++标准库中的智能指针

1. std::unique_ptr

template<class _Ty>
struct my_default_deleter
{void operator()(_Ty* ptr)const{delete ptr;}
};
template<class _Ty,class _Dx=my_default_deleter<_Ty>>
class my_unique_ptr
{
public:using element_type = _Ty;using pointer = _Ty*;using delete_type = _Dx;
private:_Ty* _mptr;delete_type mdeleter;
public:delete_type get_deleter()const { return mdeleter; }operator bool()const { return _mptr != nullptr; }my_unique_ptr(_Ty*p=nullptr):_mptr(p){}void swap(my_unique_ptr& _X){std::swap(this->_mptr, _X._mptr);  // 添加std::}pointer release()  // {pointer old = _mptr;_mptr = nullptr;return old;}void reset(pointer ptr = nullptr){mdeleter(_mptr);  // 保持原调用_mptr = ptr;}pointer get()const{return _mptr;}element_type& operator*()const {return *get();}pointer operator->()const { return get(); }my_unique_ptr(const my_unique_ptr&) = delete;~my_unique_ptr(){reset(nullptr);}my_unique_ptr(my_unique_ptr&&other) :_mptr(other._mptr){other._mptr = nullptr;}my_unique_ptr& operator=(const my_unique_ptr&) = delete;// 修正移动赋值运算符 (移除const)my_unique_ptr& operator=(my_unique_ptr&& other)  // 关键修改{if (this != &other) {reset();  // 使用reset释放资源_mptr = other._mptr;other._mptr = nullptr;}return *this;}
};

默认删除器模板 `my_default_deleter`:这是一个简单的仿函数,用于删除由`new`分配的单个对象, 它有一个成员函数 `operator()`,接受一个`_Ty*`类型的指针,然后使用`delete ptr;`释放该指针指向的对象。

`my_unique_ptr` 类模板:有两个模板参数:`_Ty`(指向的对象类型)和`_Dx`(删除器类型,默认为`my_default_deleter<_Ty>`)

element_type`: 指向的元素类型,即`_Ty`,`pointer`: 指针类型,即`_Ty*`,delete_type`: 删除器类型,即`_Dx

构造函数 my_unique_ptr(_Ty* p = nullptr)参数 p:要托管的原始指针(默认为空指针)

从原始指针创建智能指针

reset(pointer ptr = nullptr)释放当前托管对象(如果有),然后接管新对象执行流程:设置 _mptr = ptr - 接管新指针 

调用 mdeleter(_mptr) - 使用删除器释放当前资源release()放弃所有权但不释放资源返回原始指针,调用者负责管理内部指针被置空

移动构造函数 my_unique_ptr(my_unique_ptr&& other)从右值(临时对象)转移所有权复制指针后,将源对象置空源对象变为空指针状态

移动赋值运算符 operator=(my_unique_ptr&& other)从右值转移所有权处理流程:将源对象置空接管源对象的指针reset() 释放当前资源检查自赋值

析构函数 ~my_unique_ptr()自动调用 reset(nullptr) 释放资源保证资源不会泄漏

unique_ptr是唯一性智能指针所以没有拷贝构造和移动拷贝构造

基本用法

#include <memory>void uniquePtrDemo() {// 创建unique_ptrstd::unique_ptr<int> ptr1(new int(5));// C++14后推荐使用make_uniqueauto ptr2 = std::make_unique<int>(10);// 移动语义转移所有权std::unique_ptr<int> ptr3 = std::move(ptr1);// ptr1现在为空if (!ptr1) {std::cout << "ptr1 is empty now\n";}// 自动释放内存(离开作用域时)
}
特点
  • 独占所有权,不能拷贝  零额外开销(和裸指针大小相同)支持自定义删除器

2.2 shared_ptr(共享指针)

基本用法
void sharedPtrDemo() {// 创建shared_ptr(推荐make_shared)auto ptr1 = std::make_shared<int>(20);{// 共享所有权auto ptr2 = ptr1;  std::cout << "Use count: " << ptr2.use_count() << "\n";  // 2} // ptr2析构,引用计数减1std::cout << "Use count: " << ptr1.use_count() << "\n";  // 1// 自动释放内存(引用计数为0时)
}
​
timelinetitle shared_ptr 生命周期section 创建ptr1 : 对象创建(计数=1)section 共享ptr2创建 : 计数=2section 部分释放ptr2销毁 : 计数=1(对象保留)section 完全释放ptr1销毁 : 计数=0(对象释放)​

2.3 weak_ptr(弱指针)

基本用法
void weakPtrDemo() {auto shared = std::make_shared<int>(30);std::weak_ptr<int> weak = shared;// 使用前需要转换为shared_ptrif (auto temp = weak.lock()) {std::cout << "Value: " << *temp << "\n";} else {std::cout << "Object already destroyed\n";}
}

make_shared和直接构造的区别

// 方式1:两次内存分配(对象+控制块)
std::shared_ptr<Widget> p1(new Widget);// 方式2:一次内存分配(推荐)
auto p2 = std::make_shared<Widget>();
  1. 优先使用make_unique/make_shared   更高效   更安全 更简洁

  2. 不要滥用shared_ptr:默认使用unique_ptr   只在确实需要共享所有权时使用shared_ptr    shared_ptr有额外开销(控制块、原子操作)

总结

记住智能指针的黄金法则:让资源的所有权清晰明确,让资源的释放自动发生。合理使用智能指针可以显著提高C++代码的安全性和可维护性。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词