c++知识点总结--智能指针


智能指针 —避免将普通指针赋值给智能指针
引入智能指针目的:为了解决:一种是忘记或者发生异常是无法释放内存,如new完,忘记delete,另外是尚有指针引用内存的情况下释放指针,就会产生引用非法内存的指针。

auto_ptr,unique_ptr只能和new一起使用,不能和new[]使用

#include<memory>
auto_ptr<int> p(new int);
auto_ptr<int> q;
q=p;//将控制权移交给q,若在使用p,会报错
//但是使用auto_ptr上一句是合法的,若使用unique_ptr赋值会报错

1. shared_ptr

允许多个指针指向同一个对象,
默认初始化的智能指针中保存着一个空指针。

make_shared函数:
最安全的分配和使用动态内存的方法就是调用一个名为make_shared的标准库函数,此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。头文件在memory

shared_ptr<int> p3 = make_shared<int>(1);
shared_ptr<string> p4 = make_shared<string>(1,'s');
shared_ptr<int> p5 = make_shared<int>();

当该类型的指针进行拷贝和复制时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象。

auto p = make_shared<int>(42);
auto q(p);
if(p) //若p 指向一个对象,就是true;
*p  //42
//也可以使用->,总之和普通指针使用上没什么区别
p.get();//返回的是p中保存的指针
auto m = make_shared<int>(2);
swap(p,m)// p.swap(m);//交换p m 中的指针
p.unique();//若指向p中指针的智能指针只有一个,就返回true
p = m;//给p赋值,令它指向另一个地址(其中m也是一个shared_ptr)
//递增m指向的对象的引用计数
//递减p原来指向的对象的引用计数
//p原来指向的对象已没有引用者,会自动释放
//总结:当某一个对象有智能指针指向时,就会自动计数,多一个shared_ptr指向,就加一,当指向该对象的指针不在指向该对象,就会减一,直到某一刻减一后没有指针指向时,就会自动释放。
shared_ptr<int> a = new int(3);//错误
int c =10;
shared_ptr<int> b = &c;//错误
p.reset();//使得p置空,不在指向其所指向的对象
p.reset(m);
p.reset(m,d);
//若p是指向其指针的唯一一个,reset 会释放该指针,若传入m,会使p指向m,d是一个删除器
	shared_ptr<int> p = make_shared<int>(1);
	int* q = p.get();
	{
		shared_ptr<int>m(q);//让智能指针指向q,则在程序块结束时,会释放m指向的内容,即q中的内容,
		//shared_ptr<int>m(p);//可以

	}
	int tem = *p;//在上面释放后,p指向的内容被释放了,则会报错

2. unique_ptr

独占所指向的对象,
某个时刻只能有一个unique_ptr指向一个给定对象,由于一个unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作。
对于两个unique_ptr赋值时,若右边的是临时的,合法,若右边的将存在一段时间,就是非法的。
如果非要将一个unique_ptr 指针指向另一个unique_ptr,可以使用std::move()

unique_ptr<T> u1; //空unique_ptr,指向类型为T的对象u1,会使用delete来释放指针
unique_ptr<T,D> u2;//u2使用一个类型为D的可调用对象来释放指针
unique_ptr<T,D> u3(d);//空unique_ptr,用类型为D的对象释放指针
T* a = u.release();//u放弃对指针的控制权,返回指针,并将u置空
u.reset();//释放u指向的对象
u.reset(q);//使得u指向q,释放原来指向的对象
u= nullptr;//也会释放指向的对象

unique_ptr<int> p1(new int(3));
unique_ptr<int> p1 = make_unique<int>(4);
//unique_ptr<int> p2 = new int(2);//error
//int a = 10;
//unique_ptr<int> p3 = &a;//error
//unique_ptr<int> p4 = p1;//error
unique_ptr<int> p5 = move(p1);//p1悬空,p5获得所有权

3. weak_ptr

辅助shared_ptr进行指针管理,将其指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。即weak_ptr不会增加引用计数。----可以打破循环引用的情况。

shared_ptr<int> s = make_shared<int>(1);
weak_ptr<int> w;
weak_ptr<int> k(s);//并不会增加s指向指针的计数
w = s;//同上
//w.reset();//w置空
int a = w.use_count();//返回w指向指针的智能指针个数
auto b = w.expired();//若use_count() == 0,返回true;判断w指向指针是否已经被销毁,若已经销毁,则返回true;
auto c = w.lock();//若有指针指针指向w指向的指针,则返回他的一个shared_ptr指针,否则返回nullptr。
w.reset();//指向清空

为什么要引入指针指针
存在两个普通指针指向同一对象时,会删除对象两次。解决办法:1、深拷贝,但是浪费空间。2、建立所有权概念,即unique_ptr和auto_ptr的策略。同一时刻,只能有一个指针指针指向该对象,删除时,也只能由该智能指针的析构函数删除。3、追踪指向对象的智能指针个数,即引用计数,只有当引用计数为0时,才删除对象。其中,auto_ptr在c++11已经废除了,因为他在两个该类指针指向指向同一个地址时不会报错也不会提醒,若在之后继续使用已经失去所有权的指针,就会在运行时报错。unique_ptr则不允许直接将2个该类指针指向同一个对象,会在编译时报错。若非要将unique_ptr的所有权交给另一个unique_ptr,只能显式的使用move()函数。虽然用完这个函数后,我们在后续的继续使用了已经失去对象的所有权的对象也会把报错,但是这样显式的使用,会提醒的我们。同时我们在使用unique_ptr时,可以先使用get()函数判断。shared_ptr运行两个同类只能指针指向同一个对象,会增加引用计数。在释放对象时,会先判断引用数值的大小,只会删除对象一次。但是shared_ptr存在循环引用的问题,故引入weak_ptr来解决。因为weak_ptr不会增加引用计数,成员函数use_count()返回指向对象的引用次数。expired()可以判断指向对象是否不存在?lock()函数可以返回一个可以的shared_ptr,从而操作对象。
shared_ptr中的循环引用怎么解决?(weak_ptr)

使用shared_ptr解决。将其中一个或两个(这里说的也只是两个的情况)shared_ptr改为weak_ptr。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值