一文梳理C++智能指针

c++智能指针主要是解决内存管理的问题,比如我们new delete需要成对的使用,否则会发生内存泄漏,智能指针很大程度上可以解决这个问题,智能指针是一个类,当超出了类的作用类时,类会自动调用析构函数进行释放;

首先介绍关于类什么时候调用析构函数;

  1. 类的生命周期结束的时候
    1. 类的生命周期结束的标志就是当类的对象不再后面存在的时候,show the code:
    2. #include        
      #include 
      #include 
      #include
      #include
      #define LL long long
      using namespace std;
      class A
      {
      public:
          A()
          {
              cout << "constructing A" << endl;
          }
          void print()
          {
              cout << a << endl;
          }
          ~A()
          {
              cout << "destructing  A" << endl;
          }
      private:
          int a;
      };
      
      int main()
      {
          A a;
          a.print();
          return 0;
      }

       

  2. 主动调用delete函数
    1. 直接调用delete函数
  3. 对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。
    1. #include        
      #include 
      #include 
      #include
      #include
      #define LL long long
      using namespace std;
      class A
      {
      public:
          A()
          {
              cout << "constructing A" << endl;
          }
          void print()
          {
              cout << a << endl;
          }
          virtual ~A()
          {
              cout << "destructing  A" << endl;
          }
      private:
          int a;
      };
      class C
      {
      public:
          C()
          {
              cout << "constructing C" << endl;
          }
          ~C()
          {
              cout << "destructing C" << endl;
          }
      private:
          int c;
      };
      
      class B :public A
      {
      public :
          B()
          {
              cout << "constructing B" << endl;
          }
          ~B()
          {
              cout << "destructing  B" << endl;
          }
      private:
          int b;
          C c;
      };
      
      int main()
      {
          A* a = new B();
          delete a;
          return 0;
      }

      首先调用基类A的构造函数,然后是私有成员C的构造函数,接着是B的构造函数,delete的时候,因为是放在栈中的,所以顺序相反,先B再C再A。

  4. auto_ptr 

    1. #include
      #include//auto_ptr的头文件
      using namespace std;
      class Test
      {
      public:
          Test(string s)
          {
              str = s;
             cout<<"Test creat\n";
          }
          ~Test()
          {
              cout<<"Test delete:"< ptest(new Test("123"));//调用构造函数输出Test creat
          ptest->setStr("hello ");//修改成员变量的值
          ptest->print();//输出hello
          ptest.get()->print();//输出hello
          ptest->getStr() += "world !";
          (*ptest).print();//输出hello world
          ptest.reset(new Test("123"));//成员函数reset()重新绑定指向的对象,而原来的对象则会被释放,所以这里会调用一次构造函数,还有调用一次析构函数释放掉之前的对象
          ptest->print();//输出123
          return 0;//此时还剩下一个对象,调用一次析构函数释放该对象
      }

      .是调用类自身的函数,->是指向对象进行调用。当我们对智能指针进行赋值时,如ptest2 = ptest,ptest2会接管ptest原来的内存管理权,ptest会变为空指针,如果ptest2原来不为空,则它会释放原来的资源,基于这个原因,应该避免把auto_ptr放到容器中,因为算法对容器操作时,很难避免STL内部对容器实现了赋值传递操作,这样会使容器中很多元素被置为NULL。判断一个智能指针是否为空不能使用if(ptest == NULL),应该使用if(ptest.get() == NULL)

    2. 成员函数

      1. get():返回一个原始的指针

      2. reset():重新绑定指向的对象

      3. release():只是把智能指针赋值为空,但是它原来指向的内存并没有被释放

  5. unique_ptr 

    1. 拥有它指向的对象

    2. 无法进行复制构造,无法进行复制赋值操作。即无法使两个unique_ptr指向同一个对象。但是可以进行移动构造和移动赋值操作

    3. 、保存指向某个对象的指针,当它本身被删除释放的时候,会使用给定的删除器释放它指向的对象

      unique_ptr 可以实现如下功能:

      1、为动态申请的内存提供异常安全

      2、讲动态申请的内存所有权传递给某函数

      3、从某个函数返回动态申请内存的所有权

      4、在容器中保存指针

  6. share_ptr 

    1. 从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。可以通过成员函数use_count()来查看资源的所有者个数。出了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放

  7. weak_ptr

    1. ​​​​​​​weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。

你可能感兴趣的:(C++合集)