目的
- 多个智能指针共同管理同一块内存
- 其核心是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存
表示方式
- 共享智能指针的初始化
a. 共享智能指针构造函数
b. 移动构造和拷贝构造函数shared<类型> 智能指针名(内存) int *ptr = new int(500); shared_ptr<int> ptr1(ptr);//指向int型内存,shared<类型> 智能指针名(内存) shared_ptr<char> ptr2(new char[20]);//使用智能指针管理一块字符数组对应的堆内存 shared_ptr<int> ptr3;//创建智能指针,但不初始化任何内存 shared_ptr<int> ptr4(nullptr);/创建智能指针,初始化为空
c. make_shared函数//移动构造 shared_ptr<int> move_ptr = move(ptr1); //拷贝构造 shared_ptr<int> copy_ptr = move_ptr;
d. reset()初始化//make_shared<类型>(数值) shared_ptr<int> makeshare_ptr = make_shared<int>(10);
class_ptr1.reset();//无参数表示只删除,不重定义初始化 class_ptr2.reset(new Test("szy"));//先删除,再重定义初始化
- 共享智能指针的使用方法
a. 共享智能智能指针的引用计数
.use_count():查看当前共享智能指针的引用计数
b. 获取原始指针shared_ptr<int> ptr1(ptr); cout << "ptr1的值:" << *ptr1 << ",ptr1管理的内存引用计数:" << ptr1.use_count() << endl;
.get():获取原始指针
c. 直接使用智能指针//获取原始指针,通过get()方法获取地址,*获取值 Test* t = class_ptr2.get();//get()智能指针的成员函数,通过.获取 t->setValue(22); t->display();
与.get()方法的区别是 .获取 和 ->获取//直接通过智能指针访问 class_ptr2->setValue(44);//指针方式->获取 class_ptr2->display();
- 共享智能指针的删除器
尽管智能指针可以通过默认删除器自动释放内存,但对于数组类型,默认删除器是无法完全释放数组中的所有元素,因此需要对默认删除器指定数组类型。
删除器也可以自定义匿名函数实现
C++11中不支持管理数组地址,但C++11之后支持//针对数组类型需要传入数组类型,否则默认删除器无法删除数字中的每一个元素 shared_ptr<Test> arr_ptr(new Test[3], default_delete<Test[]>());
细节
- 引用计数减为0时,会删除所指向的堆内存
- 只声明共享智能指针,不做初始化时,该共享智能指针的引用计数为0
- 移动构造和拷贝构造都会增加引用计数
- 使用智能指针时,->箭头方式调用的是管理的这块内存对应的对象里面的api;.点方式调用的智能指针对象里面的api,这两个api是属于不同的类中的
举例
//如果智能指针被初始化了一块有效内存,那么这块内存的引用计数 + 1,如果智能指针没有被初始化或者被初始化为 nullptr 空指针,引用计数不会 + 1。
#include <bits/stdc++.h>
using namespace std;
class Test
{
public:
Test()
{
cout << "construct Test..." << endl;
}
Test(int x)
{
cout << "construct Test, x = " << x << endl;
}
Test(string str)
{
cout << "construct Test, str = " << str << endl;
}
~Test()
{
cout << "destruct Test ..." << endl;
}
void setValue(int v){
m_num = v;
}
void display(){
cout << "成员变量m_num:" << m_num << endl;
}
private:
int m_num;
};
int main(){
//普通指针,指针的数值为500
int *ptr = new int(500);
cout << *ptr << endl;
cout << "-----------------------共享智能指针通过构造函数进行初始化-------------------------" << endl;
//指向int型内存,shared<类型> 智能指针名(内存)
shared_ptr<int> ptr1(ptr);
cout << "ptr1的值:" << *ptr1 << ",ptr1管理的内存引用计数:" << ptr1.use_count() << endl;
//使用智能指针管理一块字符数组对应的堆内存
shared_ptr<char> ptr2(new char[20]);
cout << "ptr2管理的内存引用计数:" << ptr2.use_count() << endl;
//创建智能指针,但不初始化任何内存
shared_ptr<int> ptr3;
cout << "ptr3管理的内存引用计数:" << ptr3.use_count() << endl;
//创建智能指针,初始化为空
shared_ptr<int> ptr4(nullptr);
cout << "ptr4管理的内存引用计数:" << ptr4.use_count() << endl;
cout << "-----------------------共享智能指针通过移动构造和拷贝构造函数进行初始化-------------------------" << endl;
//移动构造
shared_ptr<int> move_ptr = move(ptr1);
// cout << "ptr1的值:" << *ptr1 << ",ptr1管理的内存引用计数:" << ptr1.use_count() << endl;//error:此时ptr1中的资源已经全部转移到了move_ptr中
cout << "move_ptr的值:" << *move_ptr << ",move_ptr管理的内存引用计数:" << move_ptr.use_count() << endl;
//拷贝构造
shared_ptr<int> copy_ptr = move_ptr;
cout << "move_ptr的值:" << *move_ptr << ",move_ptr管理的内存引用计数:" << move_ptr.use_count() << endl;
cout << "copy_ptr的值:" << *copy_ptr << ",copy_ptr管理的内存引用计数:" << copy_ptr.use_count() << endl;
cout << "-----------------------共享智能指针通过make_shared进行初始化-------------------------" << endl;
shared_ptr<int> makeshare_ptr = make_shared<int>(10);//make_shared<类型>(数值)
cout << "makeshare_ptr的值:" << *makeshare_ptr << ",makeshare_ptr管理的内存引用计数:" << makeshare_ptr.use_count() << endl;
shared_ptr<Test> class_ptr1 = make_shared<Test>(30);
shared_ptr<Test> class_ptr2 = make_shared<Test>("llx");
cout << "-----------------------共享智能指针通过reset进行初始化-------------------------" << endl;
class_ptr1.reset();
cout << "class_ptr1重置指针后的的内存引用计数:" << class_ptr1.use_count() << endl;
class_ptr2.reset(new Test("szy"));
cout << "class_ptr2管理的内存引用计数:" << class_ptr2.use_count() << endl;
cout << "-----------------------使用共享智能指针-------------------------" << endl;
//获取原始指针,通过get()方法获取地址,*获取值
Test* t = class_ptr2.get();//get()智能指针的成员函数,通过.获取
t->setValue(22);
t->display();
//直接通过智能指针访问
class_ptr2->setValue(44);//指针方式->获取
class_ptr2->display();
cout << "-----------------------共享智能指针删除器-------------------------" << endl;
//针对数组类型需要传入数组类型,否则默认删除器无法删除数字中的每一个元素
shared_ptr<Test> arr_ptr(new Test[3], default_delete<Test[]>());
// system("pause");
return 0;
}
运行结果
参考学习
https://www.bilibili.com/video/BV1bX4y1G7ks