C++ 智能指针

智能指针分为:auto_ptr、shared_ptr、weak_ptr、unique_ptr。
智能指针主要作用:
1、防止忘记调用delete释放内存;
2、管理在堆上分配的内存,它将普通的指针封装为一个栈对象,实质是一个对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。

  • shared_ptr

    • 1、定义

      shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁;

    • 2、方法

      成员函数作用
      use_count()查看资源的所有者个数
      new()构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造
      release()当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放
      unique()返回是否是独占所有权( use_count 为 1)
      swap()交换两个 shared_ptr 对象(即交换所拥有的对象)
      reset ()放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少
      get返回内部对象(指针), 由于已经重载了()方法, 因此和直接使用对象是一样
    • 3、例子

      	string *s1 = new string("s1");
      
      	shared_ptr<string> ps1(s1);
      	shared_ptr<string> ps2;
      	ps2 = ps1;
      
      	cout << ps1.use_count()<<endl;	//2
      	cout<<ps2.use_count()<<endl;	//2
      	cout << ps1.unique()<<endl;	//0
      
      	string *s3 = new string("s3");
      	shared_ptr<string> ps3(s3);
      
      	cout << (ps1.get()) << endl;	//033AEB48
      	cout << ps3.get() << endl;	//033B2C50
      	swap(ps1, ps3);	//交换所拥有的对象
      	cout << (ps1.get())<<endl;	//033B2C50
      	cout << ps3.get() << endl;	//033AEB48
      
      	cout << ps1.use_count()<<endl;	//1
      	cout << ps2.use_count() << endl;	//2
      	ps2 = ps1;
      	cout << ps1.use_count()<<endl;	//2
      	cout << ps2.use_count() << endl;	//2
      	ps1.reset();	//放弃ps1的拥有权,引用计数的减少
      	cout << ps1.use_count()<<endl;	//0
      	cout << ps2.use_count()<<endl;	//1
      
  • weak_ptr

    • 1、定义

      weak_ptr是用来解决shared_ptr相互引用时的死锁问题,可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少,观测资源的使用情况

    • 2、创建

      1、可以创建一个空 weak_ptr 指针
      std::weak_ptr<int> wp1;
      
      2、凭借已有的 weak_ptr 指针,可以创建一个新的 weak_ptr 指针
      std::weak_ptr<int> wp2 (wp1);
      
      3、weak_ptr 指针更常用于指向某一 shared_ptr 指针拥有的堆内存,因为在构建 weak_ptr 指针对象时,可以利用已有的 shared_ptr 指针为其初始化
      std::shared_ptr<int> sp (new int);
      std::weak_ptr<int> wp3 (sp);
      wp3 指针和 sp 指针有相同的指针。再次强调,weak_ptr 类型指针不会导致堆内存空间的引用计数增加或减少
      
    • 2、成员函数

      成员函数作用
      use_count()观测资源的引用计数
      expired()表示被观测的资源(也就是shared_ptr的管理的资源)已经不复存在,等价于use_count()==0
      lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr
      operator=()重载 = 赋值运算符,是的 weak_ptr 指针可以直接被 weak_ptr 或者 shared_ptr 类型指针赋值。
      swap(x)其中 x 表示一个同类型的 weak_ptr 类型指针,该函数可以互换 2 个同类型 weak_ptr 指针的内容
      reset()将当前 weak_ptr 指针置为空指针
    • 3、例子

      #include <iostream>
      #include <memory>
      using namespace std;
      int main()
      {
      std::shared_ptr<int> sp1(new int(10));
      std::shared_ptr<int> sp2(sp1);
      std::weak_ptr<int> wp(sp2);
      输出和 wp 同指向的 shared_ptr 类型指针的数量
      cout << wp.use_count() << endl;   //   2
      释放 sp2
      sp2.reset();
      cout << wp.use_count() << endl;  //  1
      借助 lock() 函数,返回一个和 wp 同指向的 shared_ptr 类型指针,获取其存储的数据
      cout << *(wp.lock()) << endl;  //   10
      return 0;
      }
      
  • unique_ptr

    • 1、定义

      一个对象和其对应的资源同一时间只被一个pointer拥有。一旦拥有者被销毁或者变成empty或者开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。
      unique_ptr具有->和*运算符重载符,因此它可以像普通指针一样使用。

    • 2、创建

      1、可以用原始指针当实参传给构造函数
      unique_ptr<int> up1(new int(1));
      
      2、make_unique函数
      unique_ptr<string> up2 = make_unique<string>("hello");
      
      3int* p = new int;
      unique_ptr<int> up3(p);//ok
      unique_ptr<int> up4(up3);//error,不可以对unique_ptr执行copy或者assign操作,只能move
      unique_ptr<int> up5 = up3; //error
      unique_ptr<int> up6(move(up3));//ok
      
    • 3、成员函数

      • 1)release()

        放弃对指针的控制权,即切断了智能指针和其所指向的对象之间的联系。返回裸指针,将该智能指针置空。
        返回的这个裸指针我们可以手动delete来释放,也可以用来初始化另外一个智能指针,或者给另外一个智能指针赋值。

        unique_ptr<string> ps1(new string("I Love China!"));
        unique_ptr<string> ps2(ps1.release()); // release后,ps1 == nullptr
        
        // 错误:
        ps2.release(); // 会导致内存泄漏
        
        unique_ptr<string> ps1(new string("I Love China!"));
        unique_ptr<string> ps2(ps1.release()); // release后,ps1 == nullptr
        
        // 正确:
        string* p = ps2.release(); // 可以简写为auto p = p2.release();
        delete p; // 手动delete释放
        
      • 2) move()

        unique_ptr<string> ps1(new string("hello!"));
        unique_ptr<string> ps2 = move(ps1); // 移动后,ps1为空,ps2指向原来ps1所指
        
      • 3) reset()

        reset() 不带参数:释放智能指针所指向的对象,并将智能指针置空。

        unique_ptr<string> ps1(new string("hello"));
        ps1.reset(); // reset后,ps1 == nullptr
        

        reset() 带参数:释放智能指针所指向的对象,并让该智能指针指向新对象。

        unique_ptr<string> ps1(new string("I Love China1!"));
        unique_ptr<string> ps2(new string("I Love China2!"));
        ps1.reset(ps2.release());
        // release后,ps2被置空;reset后,释放ps1指向的对象内存,让ps1指向ps2所指向的内存
        
        
      • 4) nullptr

        释放智能指针所指向的对象,并将智能指针置空。

        unique_ptr<string> ps1(new string("hello"));
        ps1 = nullptr; // 释放ps1所指向的对象,并将ps1置空
        
      • 5) get()

        返回智能指针中保存的裸指针
        ps是一个智能指针,p是一个普通指针:
        p = ps.get(); 后,ps并非被释放,也就相当于指针p和智能指针ps共同管理一个对象,所以就*p做的一切,都会反应到bar指向的对象上。

      • 6) swap()

        unique_ptr<string> ps1(new string("hello!"));
        unique_ptr<string> ps2(new string("world"));
        ps1.swap(ps2);
        
    • 4、例子

      #include <iostream>
      #include <memory>
      using namespace std;
      
      struct Task {
          int mId;
          Task(int id) :mId(id) {
              cout << "Task::Constructor" << endl;
          }
          ~Task() {
              cout << "Task::Destructor" << endl;
          }
      };
      
      int main()
      {
          通过原始指针创建 unique_ptr 实例
          shared_ptr<Task> taskPtr(new Task(23));
          int id = taskPtr->mId;
      
          调用其lock函数来获得shared_ptr示例,进而访问原始对象。
          weak_ptr<Task> weak1 = taskPtr;
          int id = weak1.lock()->mId;
      
          unique_ptr<Task> taskPtr(new Task(23));
          int id = taskPtr->mId;
      
          cout << id << endl;
      
          return 0;
      }
      
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++智能指针是一种用于管理动态分配的内存资源的工具。C++中提供了多种类型的智能指针,其中包括shared_ptr、unique_ptr和weak_ptr。这些智能指针都位于头文件<memory>中。 其中,shared_ptr是一种引用计数智能指针,它允许多个智能指针共享同一个对象。shared_ptr通过对对象的引用计数来管理内存的释放,当引用计数为0时,即没有智能指针指向该对象时,对象会被自动释放。使用shared_ptr需要包含头文件<memory>,并通过new关键字创建动态分配的对象并将其交给shared_ptr进行管理。 另一种智能指针是unique_ptr,它是一种独占型智能指针,只能有一个智能指针拥有对对象的所有权。当unique_ptr对象被销毁时,它所管理的对象也会被自动释放。unique_ptr提供了更高效的内存管理方式,因为它不需要进行引用计数。使用unique_ptr也需要包含头文件<memory>,并使用new关键字创建动态分配的对象并将其交给unique_ptr进行管理。 除了shared_ptr和unique_ptr,还有其他类型的智能指针,如weak_ptr和scoped_ptr。weak_ptr是一种弱引用智能指针,它用于解决shared_ptr可能出现的循环引用问题。scoped_ptr是一种简单的智能指针,它只能在创建时初始化,并且不能进行复制和赋值操作。scoped_ptr在其所属的作用域结束时自动释放所管理的对象。 总结起来,C++智能指针是一种用于管理动态分配的内存资源的工具,包括shared_ptr、unique_ptr、weak_ptr和scoped_ptr等类型。它们提供了一种更安全、更高效的内存管理方式,避免了手动释放内存的麻烦。要使用这些智能指针,需要包含头文件<memory>,并通过new关键字创建动态分配的对象并将其交给相应的智能指针进行管理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C++ -- 智能指针C++11与boost库的智能指针及其使用)](https://blog.csdn.net/xu1105775448/article/details/80625936)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [C++智能指针的底层实现原理](https://blog.csdn.net/ArtAndLife/article/details/120793343)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值