C++11 智能指针

本文详细介绍了C++标准库中的三种智能指针shared_ptr、unique_ptr和weak_ptr,它们在内存管理、线程安全和避免循环引用方面的特性和应用场景,帮助理解如何通过智能指针实现更安全、高效的动态内存管理。
摘要由CSDN通过智能技术生成

为了更加容易安全的管理动态内存,新的标准库提出了两种智能指针类型来管理动态对象;两种指针的区别是管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr 独占所指向对象;weak_ptr 是一种弱引用。在<memory>头文件中

1、shared_ptr:

  • ① 对象需要共享时用shared_ptr,智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化,不能将指针直接赋值给一个智能指针,一个是类,一个是指针,使用make_shared初始化。多个指针指向相同的对象。
  • ② shared_ptr使用引用计数,到 0 释放内存。拷贝一个shared_ptr,计数器增加(作为函数的返回值;作为参数传递给一个函数;一个shared_ptr初始化另一个shared_ptr),计数器递减(shared_ptr赋新值;shared_ptr被销毁)(r = p,递增p,递减r)。
  • ③ 注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存。
  • 应用场景: 要把指针存入标准库容器; 某一个对象的复制操作很费时,传递指向这个对象的指针来代替传递对象本身,起到了向函数传递对象的作用,又不用为释放对象操心;

线程安全问题:

  • 同一个 shared_ptr 被多个线程“读”是安全的。
  • 同一个 shared_ptr 被多个线程“写”是不安全的。(证明:在多个线程中同时对一个shared_ptr循环执行两遍swap。shared_ptr的swap函数的作用就是和另外一个 shared_ptr 交换引用对象和引用计数,是写操作。执行两遍swap之后,shared_ptr引用的对象的值应该不变)
  • 共享引用计数的不同的shared_ptr被多个线程 ”写” 是安全的。
使用make_shared函数分配和使用动态内存,make_shared需要指明对象的类型
share_ptr<int> p1 = make_shared<int>(42);   // 指向值为42的int的shared_ptr
auto p2 = make_shared<string>();  // p2指向一个动态分配的空string

share的拷贝和赋值
auto p1 = make_shared<int>(20);
auto q(p);    //p和q指向相同对象,有两个引用者

auto p2 = make_shared<int>(30);
p2 = q; //给p2赋值
        //递增q指向对象引用计数
        //递减p2原来指向对象的引用计数
        //当p2原来对象没有引用者,会自动释放

2、unique_ptr:

  • ① unique_ptr”唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象,离开作用域时,若其指向对象,则将其所指对象销毁(默认delete)。
  • ② 定义unique_ptr时,需要将其绑定到一个new返回的指针上。
  • ③ unique_ptr不支持普通的拷贝和赋值(因为拥有指向的对象),但是可以拷贝和赋值一个将要被销毁的unique_ptr;可以通过release或者reset将指针所有权从一个(非const)unique_ptr转移到另一个unique。

3、weak_ptr: 避免shared_ptr循环引用

循环引用:假设man内部有个用于管理wife生命期的shared_ptr变量,woman内部也有一个管理husband生命期的shared_ptr变量,最后两人都死不掉,违反了自然规律,导致了内存泄漏。

解决:两个类中的一个成员变量改为weak_ptr对象,因为weak_ptr不会增加引用计数,使得引用形不成环。

  • ① weak_ptr是为了配合shared_ptr而引入的一种智能指针,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况,但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。
  • ② 和shared_ptr指向相同内存,shared_ptr析构之后内存释放,在使用之前使用函数lock()检查weak_ptr所指对象是否存在,返回一个指向共享对象的shared_ptr。

细节:

  • weak_ptr虽然是一个模板类,但是不能用来直接定义指向原始指针的对象。
  • weak_ptr接受shared_ptr类型的变量赋值,但是反过来是行不通的,需要使用lock函数。
  • weak_ptr设计之初就是为了服务于shared_ptr的,所以不增加引用计数就是它的核心功能。
  • 由于不知道什么之后weak_ptr所指向的对象就会被析构掉,所以使用之前请先使用expired函数检测一下。

4、为什么要使用智能指针,用在什么地方?

  • 方便管理堆内存。使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题等。
  • 智能指针是利用了一种叫做RAII(资源获取即初始化)的技术对普通的指针进行封装,这使得智能指针实质是一个对象,行为表现的却像一个指针。
  • 智能指针的作用是防止忘记调用delete释放内存和程序异常的进入catch块忘记释放内存。另外指针的释放时机也是非常有考究的,多次释放同一个指针会造成程序崩溃,这些都可以通过智能指针来解决。
  • 智能指针还有一个作用是把值语义转换成引用语义
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值