C++ 智能指针unique_ptr、shared_ptr、weak_ptr

 在使用基本指针类型时,需要手动释放指针指向的内存,容易造成内存泄漏。而智能指针类型就是将基本指针类型封装成模板类,以便更好地管理内存。智能指针就是一个,当超出类的作用域时,编译器会自动调用析构函数,自动释放资源,所以智能指针的作用原理就是函数结束时自动释放空间,无需手动释放内存空间。

智能指针的初始化&&赋值

智能指针拥有explicit构造函数,因此普通指针类型不能隐式转换成智能指针,需要显式调用

1 shared_ptr<int> sp;//定义shared指针
2 int*p = new int;//定义普通指针
3 sp = shared_ptr<int>(p); // 显式转换
4 shared_ptr<int> sp(p); // 显式转换

错误使用:

1 int*p = new int;//定义普通指针
2 shared_ptr<int> sp=p;//定义shared指针,隐式转换 ❌

头文件

 1 #include <memory> 

unique_ptr指针使用

创建空unique_ptr指针

1 std::unique_ptr<int> u_p1();
2 std::unique_ptr<int> u_p2(nullptr);

创建unique_ptr指针,且明确指向

1 std::unique_ptr<int> u_p3(new int);

创建空unique_ptr指针,且明确指向已经存在的unique_ptr指针内存

1 std::unique_ptr<int> u_p4(new int);
2 std::unique_ptr<int> u_p5(std::move(u_p4));//调用移动构造函数
3 //u_p5 将获取 u_p4 所指堆空间的所有权,而 u_p4 将变成空指针(nullptr)。
4 std::unique_ptr<int> u_p6(std::u_p5.release());//调用移动构造函数
5 //u_p5指针释放,u_p6将指向u_p5释放前指向的内存

shared_ptr指针使用

shared_ptr采用引用计数,每一个shared_ptr的拷贝都指向相同的内容,当最后一个shared_ptr析构的时候,内存被释放

创建空shared_ptr指针

1 std::shared_ptr<int> s_p1();
2 std::shared_ptr<int> s_p2(nullptr);

创建shared_ptr指针,且明确指向

 1 std::shared_ptr<int> s_p1(new int);//use_count++
 2 cout << "s_p1引用计数:" << s_p1.use_count() << endl;
 3 std::shared_ptr<int> s_p2 = s_p1;//use_count++
 4 cout << "s_p1引用计数:" << s_p1.use_count() << endl;
 5 {
 6     std::shared_ptr<int> s_p3(s_p2);//use_count++
 7     cout << "s_p1引用计数:" << s_p1.use_count() << endl;
 8 }//超出作用域,s_p3被释放,use_count--
 9 cout << "s_p1引用计数:" << s_p1.use_count() << endl;
10 {
11     std::shared_ptr<int> s_p4(std::move(s_p2));//s_p4引用s_p2指向内存,s_p2释放为空,use_count不变
12     cout << "s_p1引用计数:" << s_p1.use_count() << endl;
13 }//超出作用域,s_p4被释放,use_count--
14 cout << "s_p1引用计数:" << s_p1.use_count() << endl;

输出结果

s_p1引用计数:1
s_p1引用计数:2
s_p1引用计数:3
s_p1引用计数:2
s_p1引用计数:2
s_p1引用计数:1

weak_ptr指针使用

使用 shared_ptr 时, 如果存在循环引用, 将导致内存泄露.weak_ptr指针 是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少.

weak_ptr 为弱引用, 可以避免此问题, weak_ptr 在功能上类似于普通指针, 然而一个比较大的区别是, 弱引用能检测到所管理的对象是否已经被释放, 从而避免访问非法内存。
注意: 虽然通过弱引用指针可以有效的解除循环引用, 但这种方式必须在程序员能预见会出现循环引用的情况下才能使用, 也可以是说这个仅仅是一种编译期的解决方案, 如果程序在运行过程中出现了循环引用, 还是会造成内存泄漏.

创建weak_ptr指针

1 std::shared_ptr<int> s_p(new int(10));
2 std::weak_ptr<int> w_p(s_p);//赋值方式1 s_p.use_count不变
3 cout << s_p.use_count()<<"   "<<*(w_p.lock()) << endl;
4 w_p = s_p;//赋值方式2
5 cout << s_p.use_count() << "   " << *(w_p.lock()) << endl;

输出结果

2   10
2   10


posted @ 2022-03-07 10:37  hik_老鬼  阅读(63)  评论(0)    收藏  举报