【C++】智能指针 Smart Pointer
智能指针
- 智能指针 Smart Pointer
- auto_ptr
- 智能指针的自实现
- shared_ptr
- weak_ptr
- unique_ptr
智能指针 Smart Pointer
用来改善传统指针的问题
需要手动管理内存
容易发生内存泄露(忘记释放、出现异常等)
比如:
一旦test()抛出异常,p指针的内存就不会被释放,发生内存泄露。释放后产生野指针
智能指针就是为了解决传统指针存在的问题
- auto_prt:属于C++98标准,在C++11已不推荐使用(有缺陷,比如不能用于数组
- shared_ptr:属于C++11标准
- unique_ptr:属于C++11标准
auto_ptr
class Person {int m_age;
public:Person() {cout << "Person()" << endl;}Person(int age): m_age(age) {cout << "Person(int)" << endl;}~Person() {cout << "~Person()" << endl;}void run() {cout << "run()" << endl;}
};void test() {// 可以理解为:智能指针p指向了堆空间的Person对象auto_ptr<Person> p(new Person(20));p->run();
}int main() {test();getchar();return 0;
}// 输出:
// Person(int)
// run()
// ~Person()
// 并没有调用析构函数,但会自动调用
智能指针不能指向栈空间的对象!因为智能指针是堆空间指针,析构时会double free!
{Person person(20); // 创建在栈空间auto_ptr<Person> p(&person); // 堆空间指针指向栈空间对象p->run();// 会调用两次析构函数
}
不能作用于数组
{auto_ptr<Person> p(new Person[10]); // 一个数组,里面有10个Person对象p->run();
}
// 构造函数会调用10次,但析构函数只会调用一次,然后抛出异常
可以使用shared_ptr
智能指针的自实现
template <typename T>
class SmartPointer {
private:T *m_obj;
public:SmartPointer(T *obj): m_obj(obj) {}~SmartPointer() {if (m_obj == nullptr) return;delete m_obj;}T *operator->() { // 为了可以使用T类的成员函数return m_obj;}
}; int main() {{SmartPointer<Person> p(new Person(20));p->run();// 看似是一个指针,实则是一个对象,重载了运算符}getchar();return 0;
}
shared_ptr
多个shared_ptr可以指向同一个对象,当最后一个shared_ptr在作用于范围内结束时,对象才会被自动释放
{shared_ptr<Person> p1(new Person(10));shared_ptr<Person> p2 = p1;shared_ptr<Person> p3 = p2;shared_ptr<Person> p4(p3); // 本质上都是p1// 当最后一个指针(p4)结束后,p1才会被自动释放 }
可以通过一个已存在的智能指针初始化一个新的智能指针
shared_ptr<Person> p1(new Person()); shared_ptr<Person> p2(p1);
针对数组的用法
shared_ptr<Person> ptr1(new Person[5]{}, [](Person *p) { delete[] p;}); // 传入lambda表达式表明想要怎么析构
shared_ptr的原理
一个shared_ptr会对一个对象产生强引用
每个对象都有个与之对应的强引用计数,记录着当前对象被多少个shared_ptr强引用着
- 可以通过shared_ptr的use_count函数获得强引用计数
{shared_ptr<Person> p1(new Person(10));cout << p1.use_count() << endl;shared_ptr<Person> p2 = p1;cout << p1.use_count() << endl;shared_ptr<Person> p3 = p2;cout << p1.use_count() << endl;shared_ptr<Person> p4(p3); cout << p1.use_count() << endl; } // 打印1 2 3 4
- 当有一个新的shared_ptr指向对象时,对象的强引用计数就会+1
- 当有一个shared_ptr销毁时,比如作用域结束,对象的强引用计数就会-1
- 当一个对象的强引用计数为0时(没有任何shared_ptr指向对象时),对象就会自动销毁(析构
循环引用
你强引用我,我强引用你,大家都别销毁
class Person;class Car { public:shared_ptr<Person> m_person;~Car() {cout << "~Car()" << endl;} };class Person { public:shared_ptr<Person> m_car;~Person() {cout << "~Person()" << endl;} };int main() {{shared_ptr<Person> person(new Person());shared_ptr<Car> car(new Car());person->m_car = car;car->m_person = person;// 不会析构,会造成内存泄漏}getchar();return 0; }
Person和Car的强引用计数都是2
一旦main函数内的大括号结束,栈空间的person 和car的强引用结束,但堆空间的person和car相互的强引用并不结束
所以Person和Car的强引用计数变为1,无法销毁
如何解决呢?
使用弱引用(weak_ptr)
weak_ptr
会对一个对象产生弱引用
可以指向对象解决shared_ptr的循环引用问题
class Person;class Car { public:weak_ptr<Person> m_person;~Car() {cout << "~Car()" << endl;} };class Person { public:shared_ptr<Person> m_car;~Person() {cout << "~Person()" << endl;} };int main() {{shared_ptr<Person> person(new Person());shared_ptr<Car> car(new Car());person->m_car = car;car->m_person = person;// 不会析构,会造成内存泄漏}getchar();return 0; }
当栈空间的Person和Car被销毁后,Person先销毁,因为Person强引用计数为0
Person被销毁后,Car的强引用也为0了,所以Car也会被销毁
unique_ptr
unique_ptr也会对一个对象产生强引用,它可以确保同一时间只有1个指针指向对象。
int main() {{unique_ptr<Person> p1(new Person());unique_ptr<Person> p2(p1); // 报错,不能把两个指针指向同一个对象![在这里插入图片描述](https://img-blog.csdnimg.cn/836d4fe420e64b24907529945889fda4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASGFsbHVjaW5hdGlvbg==,size_20,color_FFFFFF,t_70,g_se,x_16)}getchar();return 0;
}
- 当unique_ptr销毁时(作用域结束时),其指向的对象也就自动销毁了
- 可以使用std::move函数转移unique_ptr的所有权
int main() {unique_ptr<Person> p0;{unique_ptr<Person> p1(new Person());p0 = std::move(p1);}// 将p1的指向权转移给p0// 所以当大括号结束后p0指向的对象不销毁,因为p0的作用域getchar();return 0;
}
【C++】智能指针 Smart Pointer相关推荐
- [C++] 什么是智能指针(Smart Pointer)以及何时使用
答案 1 智能指针是一个类,它封装了一个原始的C++指针,以管理所指对象的生命期.没有单一的智能指针类型,但所有这些都尝试以实用的方式抽象原始指针. 智能指针应优先于原始指针. 如果你觉得你需要使用指 ...
- C++中智能指针的设计和使用
智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露.它的一种通用实现技术是使用引用计数(reference ...
- C++智能指针(设计和使用)
前段时间学习project Anarchy引擎,底层很多都是用的只能指针,学了之后一直没用过的,到现在终于算是见到实际作用了,现在重新温故下 智能指针(smart pointer)是存储指向动态分配( ...
- c++11 智能指针 unique_ptr、shared_ptr与weak_ptr
C++11中有unique_ptr.shared_ptr与weak_ptr等智能指针(smart pointer),定义在<memory>中. 可以对动态资源进行管理,保证任何情况下,已构 ...
- 智能指针——unique_ptr
1. 开篇 unique_ptr(唯一)是一种定义在中的智能指针(smart pointer).不能进行复制操作只能进行移动操作. unique是独特的.唯一的意思,故名思议,unique_ptr可以 ...
- 指针辨析:悬垂指针、哑指针、野指针、智能指针
原文地址:https://blog.csdn.net/zhaojinjia/article/details/8770989 悬垂指针: 1:提出的原因: 请看下面的代码片段: int *p=NULL; ...
- Effective Modern C++ 第四章,C++智能指针
智能指针 Smart Pointer 一些说明: C++98中有智能指针std::auto_ptr,在C++11中,出现std::unique_ptr.std::unique_ptr包含了std::a ...
- c语言智能指针是什么,C++ 智能指针深入解析
1. 为什么需要智能指针?简单的说,智能指针是为了实现类似于Java中的垃圾回收机制.Java的垃圾回收机制使程序员从繁杂的内存管理任务中彻底的解脱出来,在申请使用一块内存区域之后,无需去关注应该何时 ...
- c++string 加引号_C++|引用计数与shared_ptr智能指针(以实现String类为例)
C++ 中,动态内存的管理是通过一对运算符来完成的,new 用于申请内存空间,调用对象构造函数初始化对象并返回指向该对象的指针.delete接收一个动态对象的指针,调用对象的析构函数销毁对象,释放与之 ...
最新文章
- 运维工程师该干什么学些什么
- linux 系统安装配置 zabbix服务(源码安装)
- MySQL中的浮点数类型和定点数类型
- 微服务架构在云端的应用
- oracle package lock,Oracle 11g下重现library cache lock等待事件
- 什么是HLS(HTTP Live Streaming)?
- 栈和队列都是限制存取点的线性结构_栈的练习以及解析
- 利用python创建学生管理系统软件代码赏析
- Android Call requires API level 11 (current min is 8)的解决方案
- Hadoop简介 (资源)
- 关于scanf对换行的吸收
- 一文读懂C++程序的结构、执行与编译
- HTML CSS 兼容所有浏览器的自定义鼠标样式
- 2010年5月18日 小细节大隐患
- Python 操作pdf文件-合并操作 (三)
- Cholesky分解
- windows无法连接到打印机,打印处理器不存在
- 城镇化进程中的粮食生产问题
- 计算机专业学生组装电脑配置,我打算配置一台5000左右的组装台式电脑
- c语言中比较两束大小,【 C 语言吧 · 文学 · 西游记 】
热门文章
- win上mysql忘记root密码_MySQL数据库之windows下mysql忘记root密码的解决方法
- python做游戏代码_利用Python基础代码语句,实现2G时代文字小游戏,世界如此简单!...
- JSR303数据校验-2021新版
- 自考计算机及应用心得体会,自考中文专业的心得体会
- linux如何编译php扩展,linux环境下编译php扩展
- easypoi导出word表格_拒绝加班,批量将word文档中的信息高效率提取出来存储到Excel中...
- 【若依(ruoyi)】自定义layer
- 【uni-app】在新窗口中打开链接
- 南京大学计算机学院宋教授,宋曰钦教授
- oracle三种删除的区别,三种批量删除PLSQL写法效率的比对