C++ 智能指针

1、智能指针概述

智能指针本身是个类,程序员在为指针进行内存分配后,可能忘记使用delete销毁内存,为了避免这个问题,出现了智能指针。智能指针在创建时调用构造函数,在消亡时(超出使用范围以后)自动调用析构函数,这样就起到一个内存回收的作用。智能指针的对象都是栈上创建。

2、四种智能指针讲解

2.1 std::auto_ptr

std::auto_ptr属于C++98方案,C++11已经弃用。不支持复制(拷贝构造函数)和赋值(operator =),但进行该操作时编译器不会报错。该指针采用所有权模式,假设有std::auto_ptr p1和p2,此时p1已经初始化,将p1赋值给p2,则p2剥夺了p1的所有权,当程序运行时访问p1会报错,因为此时p1所指位置并不确定,因此存在潜在内存问题。

2.2 std::unique_ptr

std::unique_ptr是C++11中新增的用来替代auto_ptr的智能指针。std::unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个只能指针可以指向该对象,同时智能指针本身是一个类,在对象生命周期结束以后会自动调用析构函数释放内存,从而避免了内存泄漏问题。那么刚才说的有关std::auto_ptr出现的情况如果用std::unique_ptr替换则无法通过编译,需要赋值时调用std::move方法。

2.3 std::shared_ptr

std::shared_ptr实现共享式拥有,多个智能指针可以指向一个相同对象,该对象和其相关资源会在最后一个引用被销毁时释放。std::shared_ptr是为了解决std::auto_ptr在对象所有权上的局限性,在使用引用计数的机制上提供了可以共享所有权的智能指针。

2.4 std::weak_ptr

std::weak_ptr是一中不控制对象生命周期的智能指针,属于弱引用。它指向一个std::shared_ptr管理的对象,其设计的目的是为了配合std::shared_ptr的使用,它只能从一个std::shared_ptr或另一个std::weak_ptr对象构造,其构造和析构不会引起引用计数的增加或减少。std::weak_ptr是用来解决std::shared_ptr相互引用时的死锁问题(如果两个std::shared_ptr相互引用,那么这两个指针的引用计数永远不可能降到0,资源永远不能释放)。

3、手写实现std::shared_ptr(保证引用计数的原子性)

  1 #include <atomic>
  2 #include <string>
  3 #include <iostream>
  4 
  5 template <typename T>
  6 static void Del(T*& p)
  7 {
  8     if (p != nullptr)
  9     {
 10         delete p;
 11     }
 12     p = nullptr;
 13 }
 14 
 15 template <typename T>
 16 class CSharedPtr
 17 {
 18 public:
 19     CSharedPtr(T* ptr) : m_ptr(ptr), m_refCount(new std::atomic<int>(1))
 20     {}
 21 
 22     CSharedPtr(const CSharedPtr& other)
 23     {
 24         m_ptr = other.m_ptr;
 25         m_refCount = other.m_refCount;
 26         ++(*m_refCount);
 27     }
 28 
 29     ~CSharedPtr()
 30     {
 31         if (--(*m_refCount) == 0)
 32         {
 33             Del(m_ptr);
 34             Del(m_refCount);
 35         }
 36     }
 37 
 38     CSharedPtr& operator = (const CSharedPtr& other)
 39     {
 40         if (this != &other)
 41         {
 42             if (--(*m_refCount) == 0)
 43             {
 44                 Del(m_ptr);
 45                 Del(m_refCount);
 46             }
 47 
 48             m_ptr = other.m_ptr;
 49             m_refCount = other.m_refCount;
 50             ++(*m_refCount);
 51         }
 52         return *this;
 53     }
 54 
 55     T* Get()
 56     {
 57         return m_ptr;
 58     }
 59 
 60     int Count()
 61     {
 62         return m_refCount->load();
 63     }
 64 
 65     T* operator -> ()
 66     {
 67         return Get();
 68     }
 69    
 70     T& operator * ()
 71     {
 72         return *Get();
 73     }
 74 
 75 private:
 76     T* m_ptr;
 77     std::atomic<int>* m_refCount;
 78 };
 79 
 80 int main()
 81 {
 82     CSharedPtr<std::string> s(new std::string("hello world"));
 83     std::cout << s.Get() << " ref count is " << s.Count() << "\n";
 84 
 85     {
 86         CSharedPtr<std::string> s1(s);
 87         std::cout << s.Get() << " ref count is " << s.Count() << "\n";
 88     }
 89     std::cout << s.Get() << " ref count is " << s.Count() << "\n";
 90 
 91     {
 92         CSharedPtr<std::string> s1(s);
 93         std::cout << s.Get() << " ref count is " << s.Count() << "\n";
 94         CSharedPtr<std::string> s2(s1);
 95         std::cout << s.Get() << " ref count is " << s.Count() << "\n";
 96     }
 97     std::cout << s.Get() << " ref count is " << s.Count() << "\n";
 98 
 99     return 0;
100 }
101  
102 /* 输出
103 0xf11c30 ref count is 1
104 0xf11c30 ref count is 2
105 0xf11c30 ref count is 1
106 0xf11c30 ref count is 2
107 0xf11c30 ref count is 3
108 0xf11c30 ref count is 1
110 */
posted @ 2021-03-25 16:42  HOracle  阅读(136)  评论(0编辑  收藏  举报