智能指针

本文深入探讨了C++中的智能指针概念,包括shared_ptr和unique_ptr的使用方法,以及它们如何帮助开发者更安全地管理动态内存。通过实例演示了拷贝、赋值和释放对象的过程,强调了避免循环引用和混合使用智能与普通指针的重要性。
摘要由CSDN通过智能技术生成

相对于new,智能指针可以自动释放申请的堆空间;C++11提供了两种智能指针类型来管理动态对象。一种是shared_ptr,它允许多个指针指向同一对象;另一种是unique_ptr,它则独占所指向的对象。
1.shared_ptr类

创建一个可以指向T型对象的智能指针: shared_ptr < T > p;
默认初始化的智能指针中保存着一个空指针。

1)shared_ptr的独有操作

shared_ptr 操作解释
make_shared(args)返回一个shared_ptr,指向一个动态分配的类型为T的对象,使用args初始化此对象。
shared_ptr p(q)p是shared_ptr的拷贝,此操作会递增q中的计数器。q中的指针必须能转换为T*
p=q此操作会递减p的引用计数,递增q的引用计数;若p的引用计数变为0,则将释放其管理的内存
p.use_count()返回与p共享对象的智能指针数量,主要用于调试
p.unique()若p.use_count()为1,返回true,否则返回false

最安全的分配和使用动态内存的方法是调用make_shared的库函数,此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。此函数定义在< momery>中。

//不传递参数,对象默认初始化
shared_ptr<int> p = make_shared<int>();
auto p = make_shared<int>(43);

2)shared_ptr的拷贝与赋值
当进行拷贝和赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象:

auto p = make_shared<int>(42);//p指向的对象只有p一个引用者
auto q(p);//p和q指向相同的对象,此对象有两个引用者

可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数。一旦这个计数器为0,它就会释放自己所管理的对象及所占的内存。

 auto r = make_shared<int>(42);//r指向的对象只有一个引用者
r=q ;   //给r赋值,令它指向另一个地址
         //递增q指向的对象的引用计数
       //递减r原来指向的对象的引用计数
      //r原来指向的对象已没有引用者,会自动释放

拷贝使得对象的引用计数增加1,赋值使得原对象引用计数减1,当计数为0时,自动释放内存。后来指向的对象引用计数加1,指向后来的对象

3)使用动态内存的三个原因之一:

  1. 不知道自己需要使用多少对象
  2. 不知道所需对象的准确类型
  3. 需要在多个对象间的共享数据

2.shared_ptr和new结合使用
一般我们可以使用new返回的指针来初始化智能指针

shared_ptr<int> p2 (new int(1024));//正确,必须使用直接初始化形式
shared_ptr<int> p2  =new int(1024);//错误,不是直接初始化形式
#include <iostream>
#include <memory>

int main() 
{

        int a = 10;
        std::shared_ptr<int> ptra = std::make_shared<int>(a);
        std::shared_ptr<int> ptra2(ptra); //copy
        std::cout << ptra.use_count() << std::endl;

        int b = 20;
        int *pb = &a;
        //std::shared_ptr<int> ptrb = pb;  //error
        std::shared_ptr<int> ptrb = std::make_shared<int>(b);
        ptra2 = ptrb; //assign
        pb = ptrb.get(); //获取原始指针

        std::cout << ptra.use_count() << std::endl;
        std::cout << ptrb.use_count() << std::endl;
       system("pause");
       return 0;
}

注意:

  1. 不要混合使用普通指针和智能指针
  2. 也不要使用get函数初始化另一个智能指针或为智能指针赋值
  3. 注意避免循环引用,shared_ptr的一个最大的陷阱是循环引用,循环引用会导致堆内存无法正确释放,导致内存泄漏。

3.unique_ptr类
一个unique_ptr拥有它所指向的对象。与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,它所指向的对象也被销毁。

unique_ptr不能赋值和拷贝

unique_ptr 操作解释
u.release()u放弃对指针的控制权,返回指针,并将u置空
u.reset()释放u指向的对象
u.reset(q)令u指向的p所指的对象
u=nullptr释放u指向的对象,将u置为空
#include <iostream>
#include <memory>

int main() 
  {
      std::unique_ptr<int> uptr(new int(10));  //绑定动态对象
      //std::unique_ptr<int> uptr2 = uptr;  //不能赋值
      //std::unique_ptr<int> uptr2(uptr);  //不能拷贝
      uptr2.release(); //释放所有权
      system("pause");
      return 0;
  }


参考:

  1. https://www.cnblogs.com/wxquare/p/4759020.html
  2. c++ primer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值