C++ - 智能指针_智能指针学习

auto_ptr<A> A_PTR(new A());
auto_ptr<A>mm = A_PTR; //实质和std::move()语义一样。
cout << mm.get() << endl;
cout << A_PTR.get() << endl;
A_PTR->show();

}

int main()
{
test_auto_demo();
system(“pause”);
return 0;
}


运行结果:


![在这里插入图片描述](https://img-blog.csdnimg.cn/20191130150812785.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dpc2VyX0Q=,size_16,color_FFFFFF,t_70)


造成在这个的原因是auto\_ptr<A>mm = A\_PTR; //实质和std::move()语义一样。  
 这边A\_PTR已经把所有权转给mm,此时A\_PTR为空指针,空指针必然报错。。  
 所以unique\_ptr比auto\_ptr更加安全,实质上个人觉得应该是编译器对unique\_ptr的处理更加灵活。  
  


**二 unique\_ptr**


C++11中用来替代`auto_ptr`


拷贝构造和赋值运算符被禁用,不能进行拷贝构造和赋值运算


虽然禁用了拷贝构造和赋值运算符,但`unique_ptr`可以作为返回值,用于从某个函数中返回动态申请内存的所有权,本质上是移动拷贝,就是使用`std:move()`函数,将所有权转移。


代码示例:



class A{
public:
A(){
cout << “demo”<< endl;
}
void B(){
cout << “测试” << endl;
}
};

void unique_ptr_use()
{
unique_ptr A_ptr(new A());
A_ptr->B();
cout << A_ptr << endl;
unique_ptr demo = A_ptr; //此时编译错误,无法通过赋值的方式传递指针地址,即与demo共享同一块内存
}


由上面代码可以看出,编译`unique_ptr<A> demo = A_ptr`会报错,因为`unique_ptr`是只能单独享有对对象的独有权。  
 另外,unique\_ptr无法通过赋值的形式创建内存对象,即:


![在这里插入图片描述](https://img-blog.csdnimg.cn/20191130095550392.png)


这种方式也是错误的。



提前释放unique\_ptr对象可以通过`reset方法进行重置`


`代码示例:`



void unique_ptr_use()
{
unique_ptr A_ptr(new A());
A_ptr->B();
cout << A_ptr << endl;
A_ptr.reset();
cout << A_ptr << endl;
}


 运行结果:


![在这里插入图片描述](https://img-blog.csdnimg.cn/20191130095849651.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dpc2VyX0Q=,size_16,color_FFFFFF,t_70)


 可以看出:  
 通过reset方法 可以直接删除原始指针,并且重置为空。



我们可以通过转移所有权的方式,来使另一个指针拥有原先unique\_ptr的地址。


代码示例:



void unique_ptr_use()
{
unique_ptr A_ptr(new A());
A_ptr->B();
cout << A_ptr << endl;
unique_ptrBB = std::move(A_ptr);
cout << A_ptr << endl;
cout << BB << endl;
}


运行结果:


![在这里插入图片描述](https://img-blog.csdnimg.cn/20191130100305118.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dpc2VyX0Q=,size_16,color_FFFFFF,t_70)


通过`std::move()`方法,将A\_ptr的对象转移到BB上面,A\_ptr指针为空,BB拥有A\_ptr指向的地址。



**三 shared\_ptr**


多个指针可以指向相同的对象,调用`release()`计数`-1`,计数`0`时资源释放


`use_count()`查计数


`reset()`放弃内部所有权


`share_ptr`多次引用同一数据会导致内存多次释放


循环引用会导致死锁,


引用计数不是原子操作


`shared_ptr`可以实现多个对象共同托管一个指针,这个是`unique_ptr`做不到的。当曾经的托管对象接触对其托管时,系统会自动执行`delete p`释放内存,这样保证了内存不会泄漏。


代码示例:



void shared_ptr_use()
{
shared_ptr mm = make_shared();
mm->B();
cout <<“mm value:” << mm << endl;
shared_ptr ff(mm);
cout << “ff value:” << ff << endl;
cout << “个数为” << ff.use_count() << endl;
mm.reset();//重置
cout <<“now ff:”<< ff << endl;
cout << “个数为” << ff.use_count() << endl;
cout <<“now mm:”<< mm << endl;
}


运行结果:


![在这里插入图片描述](https://img-blog.csdnimg.cn/20191130134723227.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dpc2VyX0Q=,size_16,color_FFFFFF,t_70)



**四 weak\_ptr** 


1.解决两个`share_ptr`互相引用产生死锁,计数永远降不到0,没办法进行资源释放,造成内存泄漏的问题。


2.使用时配合`share_ptr`使用,把其中一个`share_ptr`更换为`weak_ptr`。


代码示例:



class B;
class A{
public:
A(){
cout << “A init!” << endl;
}
~A(){
cout << “A Destroy” << endl;
}
void set_quote_ptr(shared_ptrmm)
{
m_b = mm;
}
private:
shared_ptr m_b;
};

class B{
public:
B(){
cout << “A init!” << endl;
}
~B(){
cout << “A Destroy” << endl;
}
void set_quote_ptr(shared_ptrmm)
{
m_a = mm;
}
private:
shared_ptr m_a;
};

void test_ptr()
{
shared_ptra_ptr = make_shared();
shared_ptrb_ptr = make_shared();
a_ptr->set_quote_ptr(b_ptr);
b_ptr->set_quote_ptr(a_ptr);
cout << “a count” << a_ptr.use_count() << endl;
cout << “b count” << b_ptr.use_count() << endl;
}

int main()
{
test_ptr();
system(“pause”);
return 0;
}


此时他们之前存在相互引用,但是已经方法已经返回了还没稀释  
 运行结果:


![在这里插入图片描述](https://img-blog.csdnimg.cn/20191130143724138.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dpc2VyX0Q=,size_16,color_FFFFFF,t_70)


解释原因可以参考:[智能指针(三):weak\_ptr浅析\_AlbertS的博客-CSDN博客\_weakptr]( )


解释了无法析构的原因,这里简单介绍一下。主要是相互引用时,导致引用记数无法为0;所以无法调用函数进行析构。

## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/2f62f9ba19906a6b383a41a74ff5c3ff.png)

![img](https://img-blog.csdnimg.cn/img_convert/f7848c83edfb3ff0e8aee93fb0c3be56.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/7cc253d8ff5423f2316c177250f610df.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/a958b59bbe938bb192e6f7149bffb3a9.png)

![img](https://img-blog.csdnimg.cn/img_convert/f84ec1271461a8dcbf7408b4a7cb337c.png)

![img](https://img-blog.csdnimg.cn/img_convert/c23d3085d82a148394949123a7cff506.png)

![](https://img-blog.csdnimg.cn/img_convert/3915d1b2b4538f806d3c87f4fa1938ec.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


23)]

[外链图片转存中...(img-XCXCnYxo-1715542087824)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值