C++——智能指针(shared

智能指针:

是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针;

行为类似于常规指针,更容易也更安全的使用动态内存,负责自动释放所指向的对象;

智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放;

三种智能指针:shared_ptr、unique_ptr、weak_ptr,均定义在memory头文件中。

1、shared_ptr 定义:

shared_ptr允许多个对象指向同一个对象,是一个标准的共享所有权的智能指针,C++11引入到C++ STL

用法:
shared_ptrstring p1; //一个指向string类型的shared_ptr指针p1
shared_ptrlistint p2;// 一个指向int型list的shared_ptr指针p2

默认初始化的只能指针中保存着一个空指针,解引用一个智能指针返回它所指向的对象

操作:
make_sharedT (args)   返回一个shared_ptr,指向一个动态分配的类型为T的对象,用args初始化此对象
shared_ptrT p(q)      p是shared_ptr q的拷贝;该操作会递增q中的计数器,q中的指针必须能转化为T*
p=q                     p和q都是shared_ptr,所保存的指针能够相互转化;该操作递增q的引用计数,递减P的引用计数 
p.unique()              若p.use_count()为1,返回true,否则返回false
p.use_count()           返回和p共享对象的智能指针数量(主要用于调试)
p.get()                 返回p中保存的指针(返回一个内置指针,指向智能指针管理的对象 int *q=p.get())
swap(p,q)/p.swap(q)     交换p,q中的指针
p                       用作一个条件判断,若指向一个对象,最为true
*p                      解引用,获得它所指对象
p-mem                  等价于(*p).mem,获取所指对象成员
make_shared函数:

在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr,使用该函数时,必须指定想要创建的对象类型

shared_ptrint p3=make_sharedint(42) 指向一个值为42的int
shared_ptrstring p4=make_sharedstring(5,'b') 指向一个值为'bbbbb'的string的shared_ptr
shared_ptrint p5=make_sharedint() 指向一个值初始化的int,值为0

通常用auto定义一个对象来保存make_shared的结果

//p6指向一个动态分配的空vectorstring
auto p6=make_sharedvectorstring();
拷贝与赋值:

进行拷贝与赋值时,每个shared_ptr都会记录有多少的其他shared_ptr指向相同对象;

每一个shared_ptr都有一个关联计数器,叫做引用计数,拷贝时,计数器递增;

一个shared_ptr被赋予新值(改变指向对象,即不指向当前对象时)或被销毁时,计数器递减,减为0时自动释放所管理的对象。

auto r=make_sharedint(42);
r=q;//给r赋值,令它指向q所指的地址
    //递增q指向对象的引用计数
    //递减r原来所指对象(42)的引用计数
    //r原来指向的对象没有引用者会自动释放

shared_ptr的析构函数会递减他所指对象的引用计数,变为0时会销毁对象,释放它所占的内存

ps:使用动态内存的原因

     1、程序不知道自己需要使用多少对象

     2、程序不知道所需对象的准确类型

     3、程序需要在多个对象间共享数据

2、unique_str 定义:

C++11引入,替代不安全的auto_ptr,一个unique_str"拥有"它所指的对象,持有对对象的独有权。

特点:

两个unique_ptr 不能指向一个对象,即 unique_ptr 不共享它所管理的对象;

只能移动unique_ptr,即对资源管理权限可以实现转移,意味着内存资源所有权可以转移到另一个 unique_ptr,并且原始    unique_ptr 不再拥有此资源;

运行效率高,因为通过 unique_ptr 的移动构造函数,不再需要进行复制操作;

与所指对象的关系:

在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过 reset 方法重新指定、通过 release 方法释放所有权、通过移动语义转移所有权,unique_ptr 还可能没有对象,这种情况被称为 empty。

操作:
//智能指针的创建
unique_ptrint u_i; 	//创建空智能指针
u_i.reset(new int(3)); 	//绑定动态对象  
unique_ptrint u_i2(new int(4));//创建时指定动态对象
unique_ptrT,D u(d);	//创建空 unique_ptr,执行类型为 T 的对象,用类型为 D 的对象 d 来替代默认的删除器 delete

//所有权的变化   
unique_ptrstring u_s(new string("abc"));  
unique_ptrstring u_s2 = std::move(u_s); //所有权转移(通过移动语义),u_s所有权转移后,变成空指针 
u_s2.reset(u_s.release());	//所有权转移
u_s2=nullptr;//显式销毁所指对象,同时智能指针变为空指针。与u_s2.reset()等价
u.release();     //放弃控制权,返回指针,u置空  int *p_i = u_i2.release();	 
u.reset();      //释放u所指对象
u.reset(q)      //如果提供内置指针q,u指向q,否则置空
u.reser(nullptr)
3、weak_ptr 定义:

一种不控制所指对象生命周期的智能指针,它指向由一个shared_ptr管理的对象。

weak_ptr 是为了配合 shared_ptr 而引入的一种智能指针,它更像是 shared_ptr 的一个助手而不是智能指针,因为它不具有普通指针的行为,没有重载 operator* 和 operator- ,因此取名为 weak,表明其是功能较弱的智能指针。

weak_ptr 只对 shared_ptr 进行引用,而不改变其引用计数,当被观察的 shared_ptr 失效后,相应的 weak_ptr 也相应失效。

操作:
weak_ptrT w;	 	//创建空 weak_ptr,可以指向类型为 T 的对象
weak_ptrT w(sp);	//与 shared_ptr 指向相同的对象,shared_ptr 引用计数不变。T必须能转换为 sp 指向的类型
w=p;				//p 可以是 shared_ptr 或 weak_ptr,赋值后 w 与 p 共享对象
w.reset();			//将 w 置空
w.use_count();		//返回与 w 共享对象的 shared_ptr 的数量
w.expired();		//若 w.use_count() 为 0,返回 true,否则返回 false
w.lock();			//如果 expired() 为 true,返回一个空 shared_ptr,否则返回非空 shared_ptr

使用 weak_ptr 的成员函数 use_count() 可以观测资源的引用计数,另一个成员函数 expired() 的功能等价于 use_count()==0,但更快,表示被观测的资源(也就是 shared_ptr 管理的资源)已经不复存在。weak_ptr 可以使用一个非常重要的成员函数lock()从被观测的 shared_ptr 获得一个可用的 shared_ptr 管理的对象, 从而操作资源。但当 expired()==true 的时候,lock() 函数将返回一个存储空指针的 shared_ptr。

 

 

最新回复(0)
/jishu5o_2B7PcHoYqLzdX1jPNiLjNuy3mkzBC8wo5p5JMyVfCo_3D4858745
8 简首页