C++11 shared_ptr(智能指针)
在确保new动态分配的内存空间在使用结束之后,释放是一件麻烦事。C++11模板库的头文件中定义的智能指针,即shared_ptr模板,就是用来解决这个问题的。
它是将new运算符返回的指针p交给一个shared_ptr对象“托管”,就不用担心要在哪里写delete p语句 ---实际根本不需要编写这条语句,托管p的shared_ptr对象在消亡时会自动执行delete p,而且,该shared_ptr对象能像指针p一样使用,即假设托管p的shared_ptr的shared_ptr对象叫做ptr,那么*ptr就是p指向的对象。
通过shared_ptr的构造函数,可以让shared_ptr对象托管一个new运算符范围的指针,写法如下:
shared_ptr<T> ptr(new T);//T可以是int、char、类等类型
此后,ptr就可以像T*类型的指针一样使用,即*ptr就是用new 动态分配的那个对象
多个shared_ptr对象可以共同托管一个指针p,当所有曾经托管p的shared_ptr对象都解除了对其的托管时,就执行delete p
实例:
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
int i;
A(int n):i(n) { };
~A() { cout << i << " " << "destructed" << endl; }
};
int main()
{
shared_ptr<A> sp1(new A(2)); //A(2)由sp1托管,
shared_ptr<A> sp2(sp1); //A(2)同时交由sp2托管
shared_ptr<A> sp3;
sp3 = sp2; //A(2)同时交由sp3托管
cout << sp1->i << "," << sp2->i <<"," << sp3->i << endl;
A * p = sp3.get(); // get返回托管的指针,p 指向 A(2)
cout << p->i << endl; //输出 2
sp1.reset(new A(3)); // reset导致托管新的指针, 此时sp1托管A(3)
sp2.reset(new A(4)); // sp2托管A(4)
cout << sp1->i << endl; //输出 3
sp3.reset(new A(5)); // sp3托管A(5),A(2)无人托管,被delete
cout << "end" << endl;
return 0;
}
程序的输出结果如下:
2,2,2
2
3
2 destructed
end
5 destructed
4 destructed
3 destructed
可以用第 14 行及第 16 行的形式让多个 sharecLptr 对象托管同一个指针。这多个 shared_ptr 对象会共享一个对共同托管的指针的“托管计数”。有 n 个 shared_ptr 对象托管同一个指针 p,则 p 的托管计数就是 n。当一个指针的托管计数减为 0 时,该指针会被释放。shared_ptr 对象消亡或托管了新的指针,都会导致其原托管指针的托管计数减 1。
第 20、21 行,shared_ptr 的 reset 成员函数可以使得对象解除对原托管指针的托管(如果有的话),并托管新的指针。原指针的托管计数会减 1。
输出的第 4 行说明,用 new 创建的动态对象 A(2) 被释放了。程序中没有写 delete 语句,而 A(2) 被释放,是因为程序的第 23 行执行后,已经没有 shared_ptr 对象托管 A(2),于是 A(2) 的托管计数变为 0。最后一个解除对 A(2) 托管的 shared_ptr 对象会释放 A(2)。
main 函数结束时,sp1、sp2、sp3 对象消亡,各自将其托管的指针的托管计数减为 0,并且释放其托管的指针,于是会有以下输出:
5 destructed
4 destructed
3 destructed
只有指向动态分配的对象的指针才能交给 shared_ptr 对象托管。将指向普通局部变量、全局变量的指针交给 shared_ptr 托管,编译时不会有问题,但程序运行时会出错,因为不能析构一个并没有指向动态分配的内存空间的指针
注意
不能使用下面的方式使两个shared_ptr对象托管同一个指针
A* p = new A(10);
shared_ptr <A> sp1(p), sp2(p);
sp1 和 sp2 并不会共享同一个对 p 的托管计数,而是各自将对 p 的托管计数都记为 1(sp2 无法知道 p 已经被 sp1 托管过)。这样,当 sp1 消亡时要析构 p,sp2 消亡时要再次析构 p,这会导致程序崩溃。
参考链接:http://c.biancheng.net/view/430.html
C++11 shared_ptr(智能指针)的更多相关文章
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- C++11 shared_ptr智能指针(超级详细)
在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如: 有些内存资源已经被释放,但指向它的指针并没 ...
- C++11 unique_ptr智能指针详解
在<C++11 shared_ptr智能指针>的基础上,本节继续讲解 C++11 标准提供的另一种智能指针,即 unique_ptr 智能指针. 作为智能指针的一种,unique_ptr ...
- c++11之智能指针
在c++98中,智能指针通过一个模板“auto_ptr”来实现,auto_ptr以对象的方式来管理堆分配的内存,在适当的时间(比如析构),释放所获得的内存.这种内存管理的方式只需要程序员将new操作返 ...
- 标准库shared_ptr智能指针的实现
目前测试功能正常.若有不完善的地方在改进吧.时候不早了睡觉去,哎,翘课会被抓,不冒险了.晚安全世界O(∩_∩)O /****************************************** ...
- C++11中智能指针的原理、使用、实现
目录 理解智能指针的原理 智能指针的使用 智能指针的设计和实现 1.智能指针的作用 C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理.程序员自己管理堆内存可以提高了程序 ...
- C++11 weak_ptr智能指针
和 shared_ptr.unique_ptr 类型指针一样,weak_ptr 智能指针也是以模板类的方式实现的.weak_ptr<T>( T 为指针所指数据的类型)定义在<memo ...
- auto_ptr,shared_ptr 智能指针的使用
Q: 那个auto_ptr是什么东东啊?为什么没有auto_array?A: 哦,auto_ptr是一个很简单的资源封装类,是在<memory>头文件中定义的.它使用“资源分配即初始化”技 ...
- shared_ptr智能指针源码剖析
(shared_ptr)的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化.根据文档 (http://www.boost.org/doc/ ...
- shared_ptr智能指针
来自博客:https://www.cnblogs.com/lzpong/p/6188034.html 多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_p ...
随机推荐
- Java8 stream 提取对象 List 中的某一字段生成新的 List
//输出List StudentInfo.printStudents(studentList); //从对象列表中提取一列(以name为例) List<String> nameList = ...
- Powershell 调用cmd 运行exe、bat、jar文件
1. 配置路径 $nginxPath = "C:\path\to\nginx" $redisPath = "C:\path\to\redis" $ruoyiAd ...
- IOS 内付 asp.net mvc 服务器端验证
上代码: public class AppStorePayApp { public int VerifyReceipt(string receipt, out string product_id, o ...
- 【记录】C++STL容器/特有类 使用积累
STL容器共有成员函数 size() max_size() empty() begin() end() clear() [链接]csdn_STL中所有容器共有成员函数 双端队列deque 1.创建与初 ...
- 搭建自己的OCR服务,第二步:PaddleOCR环境安装
PaddleOCR环境安装,遇到了很多问题,根据系统不同问题也不同,不要盲目看别人的教程,有的教程也过时了,根据实际情况自己调整. 我这边目前是使用windows 10系统+CPU + python ...
- PIO----创建Excel表格复杂使用
导出 @RequestMapping( name = "下载模板附件实现Model", value = {"/uploadFileModel"}, method ...
- 官方的 MCP C# SDK:csharp-sdk
csharp-sdk 这是 Model Context Protocol(MCP)官方提供的 C# SDK,为 MCP 服务器和客户端提供简单易用的接口, 主要由微软维护.MCP 是由 Claude( ...
- ANSYS 启动窗口过大问题解决
方法总结(省流版):选择兼容性下更改高 DPI 设置 => 勾选高DPI 缩放代替 ,且其下对应应用程序选项 1.环境 系统环境:Windows 11 设备情况:分辨率 1920×1080:缩放 ...
- Spring Boot的常用注解
在Spring Boot中,注解(Annotation)是核心特性之一,广泛用于配置和简化开发.以下是Spring Boot中一些常用的注解及其示例: 1. @SpringBootApplicatio ...
- Javascript 对象(object)合并
转
转载了一篇介绍的比较直观的博文.