C++智能指针详解[shared_ptr、unique_ptr、weak_ptr]]

一、智能指针的由来及分类

1.程序内存分区:静态区 栈区 堆区(自由空间/动态内存)
静态内存里存储着局部static对象,类的static数据成员以及定义在任何类外的变量,栈内存里保存着定义在函数内的非static对象,分配在静态内存或栈内存中的对象有着严格的生存期,由编译器自动生成和销毁。但有时需要在程序运行时动态分配对象,这个时候就需要用到动态内存了,动态内存的生存期由程序来控制,也就是说,必须在合适的时机显式地销毁他们。即当程序在堆区存储动态分配的对象且当动态对象不再使用时,必须手动释放销毁,否则会造成内存泄漏。

2.动态内存的管理:new和delete
new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针。
delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存。

3.动态内存管理存在的问题:
1.一种是忘记释放内存,会造成内存泄漏;
2.一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针。

4.智能指针产生:
为了更加安全的的使用动态内存,引入智能指针的概念。智能指针的行为类似常规指针,最大的区别是它能够自动释放所指向的对象,利用智能指针管理动态内存可以有效降低内存泄漏的可能。

5.智能指针的种类:
1.shared_ptr: 允许多个指针指向同一个对象(引用计数器机制)
2.unique_ptr: "独占“所指对象(引用计数器最大值为1的shared_ptr)
3.weak_ptr: 弱引用,指向shared_ptr所管理的对象
注:三种智能指针都定义在的头文件中

二、shared_ptr详解
shared_ptr 是C++11提供的一种智能指针类,它可以自动删除相关指针,从而彻底消除内存泄漏和悬空指针的问题。它遵循共享所有权的概念,即不同的 shared_ptr 对象可以与相同的指针相关联,内部使用引用计数机制来实现。

1.引用计数机制:
每个 shared_ptr 对象在内部指向两个内存位置:指向对象的指针和用于控制引用计数数据的指针。
1、当新的 shared_ptr 对象与指针关联时,在其构造函数中,将与此指针关联的引用计数增加1。
2、当任何 shared_ptr 对象超出作用域时,则在其析构函数中,它将关联指针的引用计数减1。
3、如果引用计数变为0,则无shared_ptr 对象与此内存关联,它使用delete函数删除该内存。

2.shared_ptr支持的操作:

shared_ptr<T> p      //空智能指针
p                    //将p用作一个条件判断,若p指向一个对象则为ture
*p                   //解引用p,获得它指向的对象
p->member            //等价于(*p).member
p.get()              //返回p中保存的指针,小心使用
swap(p,q)            //交换p和q中的指针
p.swap(q)            //交换p和q中的指针
make_shared<T>(args) //返回一个动态分配类型为T的对象,使用args初始化此对象
shared_ptr<T>p(q)    //p 是shared_ptr q的拷贝,此操作会递增q中的计数器,q中的指针必须能转换为T*
shared_ptr<T>p(u)    //p从unique_ptr u那里接管了对象的所有权,将u置空
shared_ptr<T>p(q,d)  //p接管了内置指针q所指向的对象的所有权,p将使用可调用对象d来代替delete
p=q                  //p和q必须都是shared_ptr,所保存的指针必须能相互转换,此操作会递减p的引用计数,递增q的引用计数
p.use_count()        //返回与p共享对象的智能指针数量,可能很慢,主要用于调试
p.unique()           //若p.use_count()为1,返回ture,否则返回false
p.reset()            //分离关联的原始指针,p指向的对象引用计数减少1
p.reset(q)           //令p指向新指针q
p.reset(q,d)         //令p指向q,并调用d来代替detlete
p = nullptr          //重置指针为空指针

3.shared_ptr的定义
智能指针的本质是一个模板,和普通指针定义类似,定义指针时需要声明指针可以指向值的类型。定义普通指针时,类型写在开头,定义智能指针则把类型写在尖括号里。

//普通指针定义
int *pi;

//智能指针定义(默认初始化为空指针nullptr)
std::shared_ptr<string> p1;               //允许指向string类型的空智能指针
std::shared_ptr<int> p2;                  //允许指向int类型的空智能指针
std::shared_ptr<vector<string>> p3;       //允许只想vector<string>类型的空智能指针

4.shared_ptr的初始化
使用make_shared()函数初始化智能指针(常用)
通过传入的参数与构造类型的构造函数进行匹配并初始化,也可以不传入任何参数,默认使用值初始化的方式初始化对象。make_shared()函数make_share后面要加一个尖括号指出指针要指向的类型。

//eg1:
std::shared_ptr<int>p1 = std::make_shared<int>();
//eg2:
std::shared_ptr<int>p1 = std::make_shared<int>(10);
//eg2:
std::shared_ptr<string>p2 = std::make_shared<string>("I am a shared_ptr")

5.shared_ptr的拷贝与复制
shared_ptr在内部实现上有一个引用计数器,当进行拷贝和赋值时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象。只要拷贝一个shared_ptr,引用计数器的值就会上升,一旦引用计数器的值为0,它就会自动调用shared_ptr指向类型的析构函数释放相关联的动态内存。

auto p = make_shared<int>42;
auto q(p);//拷贝构造
r=q;//给r赋值,让它指向另一个地址
	//递增q指向的对象的引用计数
	//递减r原来指向的对象的引用计数
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值