智能指针
本文最后更新于:1 年前
针对于C++面试题,博主复习,C++11新标准的智能指针
1.概念
所谓的智能指针本质就是一个类模板,它可以创建任意的类型的指针对象,当智能指针对象使用完后,对象就会自动调用析构函数去释放该指针所指向的空间。
所有的智能指针类模板中都需要包含一个指针对象,构造函数和析构函数
2.三大智能指针
(1)unique_ptr
C++11版本库提供的智能指针,直接将拷贝构造函数和赋值重载函数给禁用掉,因此不让其进行拷贝和赋值。
1 |
|
我们通过内存查看&v1,如下图:
我们找到了堆区内存地址,我们在内存中查看该地址,如下图:
地址中即为存储的0
unique_ptr它所指向的资源对象,该资源对象不会被多个unique_ptr对象同时占有,可以称之为独占指针
此外unique_ptr还有以下特性:
1)虽然unique_ptr对象之间不能进行拷贝和赋值,但是可以进行移动,如下:
1 |
|
Tips: get()和release()的区别:
get()是返回一个裸指针但原始指针不变,unique_ptr可以和普通指针共同管理一个对象,并且普通对象的操作可以反映到unique_ptr指针所指向的对象上
就是使用v1.get()和直接使用v1是一样的效果!
而release()是返回一个裸指针并将原始指针变为NULL
个人还觉得,尽量避免智能指针和普通指针的混合,那样容易非常的乱,导致内存泄露,导致崩溃
- unique_ptr 没有重载加减运算符 但是可以通过普通指针来进行操作
1 |
|
同时我们使用get()函数获取原始指针后,最后不需要delete,因为和智能指针指向同一片堆区内存,智能指针脱离生命周期后会自动析构,所以普通指针也会被销毁掉,因此不需要执行销毁操作。
更多
- 使用unique_ptr实现虚拟多态
1 |
|
- 自定义删除器
1 |
|
(2)shared_ptr
结构:有两个成员,第一成员是原始指针,为从堆区申请的动态内存空间的地址
第二成员是用于引用计数的内存对象,是由_Ref_count_base类继承而来的 _Ref_count类创建的对象
该对象有四个成员:
第一个成员为虚表地址:因为是派生类的对象,调用了父类的虚函数
第二个成员为**__Users**:
第三个成员为**__Weaks**
第四个成员为原始指针
其构造函数和unique_ptr不同点在于,其有一个计数器
而且,shared_ptr可以进行拷贝赋值
每进行一次拷贝赋值**__Users就需要++**操作
并且在拷贝构造后,v2和v1会指向同一片内存
1 |
|
不能使用原始指针对shared_ptr初始化
错误例子:
1 |
|
自定义删除器:
1 |
|
使用shared_ptr传参时,也会影响Users++ 相当于又创建了一个对对象的引用指针
新标准支持使用中括号对智能指针数组进行访问
返回值类型为shared_ptr时,也会造成**_Users++** ,前提是,函数内部中的shared_ptr是静态的(生命周期全局,引用数不–),如果非静态,当离开当前作用域后就会自动调用析构函数(引用数–)
(2)weak_ptr
辅助shared_ptr使用
解决循环引用的问题
//shared_ptr赋予一个新值
//shared_ptr为局部变量离开了作用域,或是shared_ptr被销毁
解决方案:
将其中一个类成员shared_ptr指针更改为weak_ptr
weak_ptr与shared_ptr结构一致
不能单独被new出来,只能辅助shared_ptr
与shared_ptr指向同一片内存时,其内部的_Users不会++
1 |
|
1.当MyClass1和MyClass2中都有一个shared_ptr成员m_1时,整个程序结束后,v1和v2的引用计数都是1,没有为0,产生内存泄漏。
2.当有一个为weak_ptr时,假设是Myclass1中m_1为weak_ptr,这时 v1 -> m_1 = v2 后,v2只有一次引用计数,v2析构后,其为0。当v1析构后,此时MyClass2中的m_1消失,v1引用计数变为1,然后,因为v1析构,其引用计数再–,变为0