活动介绍
file-type

C++智能指针详解:unique_ptr, weak_ptr, shared_ptr, auto_ptr

5星 · 超过95%的资源 | 下载需积分: 50 | 111KB | 更新于2024-08-05 | 123 浏览量 | 6 下载量 举报 收藏
download 立即下载
"本文主要介绍了C++中的四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr,包括它们的使用方式、工作机制以及可能存在的缺陷。智能指针是为了解决C++中动态内存管理和指针操作可能导致的问题,如内存泄漏和内存损坏等。" 在C++中,智能指针是一种特殊的类,它包装了一个原始指针,并负责在适当的时候自动释放内存。这极大地提高了代码的安全性和可维护性。 1. **auto_ptr**: 是C++标准库中的第一个智能指针,但在C++11之后已被弃用。auto_ptr具有所有权的概念,即一个auto_ptr对象独占所指向的对象的所有权。当一个auto_ptr被赋值或拷贝时,原始指针的所有权会被转移,旧的所有者会变为空指针。这种行为在某些情况下可能导致安全问题,比如解引用空指针。因此,auto_ptr不支持复制构造函数和赋值运算符,而是使用移动语义。 使用示例: ```cpp std::auto_ptr<int> ptr1(new int(5)); std::auto_ptr<int> ptr2(ptr1); // ptr1现在为空,ptr2拥有int对象 ``` 2. **unique_ptr**: 是C++11引入的替代auto_ptr的智能指针。unique_ptr同样遵循所有权原则,但不允许复制,只允许移动。这意味着unique_ptr不能被赋值,但可以通过std::move进行转移所有权。 使用示例: ```cpp std::unique_ptr<int> ptr1(new int(5)); std::unique_ptr<int> ptr2 = std::move(ptr1); // ptr1现在为空,ptr2拥有int对象 ``` 3. **shared_ptr**: 允许多个shared_ptr共享同一块内存。它通过内部的引用计数来跟踪有多少个shared_ptr指向同一对象。当最后一个shared_ptr析构时,会自动删除其所指向的对象。这可能导致的问题是循环引用,即两个或多个shared_ptr相互引用,导致无法正确释放内存。 使用示例: ```cpp std::shared_ptr<int> ptr1(new int(5)); std::shared_ptr<int> ptr2(ptr1); // ptr1和ptr2都指向同一int对象 ``` 4. **weak_ptr**: 是为了配合shared_ptr设计的,它不拥有对象,但可以观察shared_ptr所拥有的对象。当所有共享此对象的shared_ptr都被销毁后,weak_ptr不会阻止对象的析构,因此可以防止循环引用的问题。weak_ptr需要先检查是否仍然有效(即对象尚未被销毁)才能使用。 使用示例: ```cpp std::shared_ptr<int> ptr1(new int(5)); std::weak_ptr<int> weakPtr(ptr1); if (std::shared_ptr<int> strongPtr = weakPtr.lock()) { // 使用strongPtr } ``` 智能指针提供了一种安全的方式来管理动态内存,避免了传统指针可能出现的错误。unique_ptr适用于单个所有者的情况,而shared_ptr则用于需要共享所有权的场景。weak_ptr作为辅助工具,可以解决shared_ptr的循环引用问题。在编写C++程序时,应根据实际需求选择合适的智能指针类型。

相关推荐

filetype

#pragma once #include<functional> namespace dfq { //给什么类型就形成什么指针 //RAII利用对象的生命周期来控制资源的获取释放 template<class T> class auto_ptr { public: auto_ptr(T* ptr = nullptr) :_ptr(ptr) { } ~auto_ptr() { delete _ptr;//运用包装器,释放资源free\delete\delete[] } //拷贝构造 //sp1(sp2) auto_ptr(auto_ptr<T>& sp) :_ptr(sp._ptr) { sp._ptr = nullptr;//被拷贝指针悬空,不推荐 } //像指针一样 T* operator->() { return _ptr; } T& operator*() { return *_ptr; } private: T* _ptr; }; template<class T> class unique_ptr { public: unique_ptr(T* ptr = nullptr) :_ptr(ptr) { } ~unique_ptr() { delete _ptr;//运用包装器,释放资源free\delete\delete[] } //拷贝构造、赋值重载不执行,指针之间就不能赋值 //sp1(sp2) unique_ptr(unique_ptr<T>& sp) = delete; unique_ptr<T>& operator=(unique_ptr<T>& sp) = delete; //像指针一样 T* operator->() { return _ptr; } T& operator*() { return *_ptr; } private: T* _ptr; }; template<class T> class shared_ptr { public: shared_ptr(T* ptr = nullptr) :_ptr(ptr) ,_pcount(new int(1))//指针对象创建时,说明刚好申请一块资源 //此时只有一个指针指向该资源 {} //只穿一个参数,无法实例化出下面这个构造函数 template<class D> shared_ptr(T* ptr, D del = [](T* ptr) {delete ptr; }) :_ptr(ptr) , _pcount(new int(1)) ,_del(del)//定制删除器,传什么怎么删除 { } //拷贝构造,新增一个指针指向该资源,引用计数++ //sp1(sp2) shared_ptr(const shared_ptr<T>& sp) :_ptr(sp._ptr) ,_pcount(sp._pcount) { ++(*_pcount); } //赋值重载: //ap1 = ap2; shared_ptr<T>& operator=(shared_ptr<T>& sp) { //1.指向同一块资源的指针没必要赋值 if (_ptr == sp._ptr) return *this; //2.指向不同资源的指针间赋值需注意 //前一块资源的释放问题,后一资源引用计数++ if (--(*_pcount) == 0) { _del(_ptr); delete _pcount; _ptr = nullptr; _pcount = nullptr; } _ptr = sp._ptr; _pcount = sp._pcount; ++(*_pcount); } ~shared_ptr() { if (--(*_pcount) == 0) { _del(_ptr); delete _pcount; _ptr = nullptr; _pcount = nullptr; } } //像指针一样 T* operator->() { return _ptr; } T& operator*() { return *_ptr; } T* get() { return _ptr; } int use_count() { return *_pcount; } private: T* _ptr; int* _pcount;//引用计数,有多少个指针指向该资源 function<void(T*)> _del = [](T* ptr) {delete ptr; }; //释放资源的函数类型一致,且默认为delete }; template<class T> class weak_ptr { public: weak_ptr(T* ptr = nullptr) :_ptr(ptr) {} //sp1(sp2) weak_ptr(const shared_ptr<T>& sp) :_ptr(sp.get()) {} weak_ptr(const weak_ptr<T>& sp) :_ptr(sp._ptr) {} //ap1 = ap2; weak_ptr<T>& operator=(weak_ptr<T>& sp) { //1.指向同一块资源的指针没必要赋值 if (_ptr == sp._ptr) return *this; _ptr = sp._ptr; } weak_ptr<T>& operator=(shared_ptr<T>& sp) { //1.指向同一块资源的指针没必要赋值 if (_ptr == sp.get()) return *this; _ptr = sp.get(); } //像指针一样 T* operator->() { return _ptr; } T& operator*() { return *_ptr; } T* get() { return _ptr; } private: T* _ptr;//不参与资源管理,只是简单的访问 }; } 仔细评价这份实现,重点在于unique_ptr\shared_ptr\weak_ptr

大酷茬子
  • 粉丝: 2
上传资源 快速赚钱