C++智能指针
2021/4/10 12:30:40
本文主要是介绍C++智能指针,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
首先得说一下为何要使用智能指针:
当程序中出现了动态分配内存的时候,程序员需要在程序中用delete去释放之前动态分配的内存,如果不这么做,会造成内存泄露,例如:
1 int* p = new int; 2 delete p;
虽然delete可以释放内存,但是这种需要程序员自己记住手动释放内存的方式很容易出现问题。比如当程序中出现了异常处理或者是提前结束程序的部分,留在程序末尾的delete可能就不会执行,这样的话一开始动态分配的内存就会出现内存泄漏的问题,造成很多麻烦。
所以C++有一种非常智能的指针去避免这个问题,就是auto_ptr,也就是C++98中的最原始的智能指针。智能指针的实现原理就是一个类,这个类的构造函数就是将自身的成员指针指向外界的动态分配的内存。这么做的目的主要是为了利用C++类中的析构函数,因为当类的生命周期结束的时候,对象会自动调用析构函数进行delete操作,自动的完成了内存释放的操作,非常方便也非常智能。
但auto_ptr也只是个简单的智能指针,它有一些问题,比如:
1 std::auto_ptr<MyObject> p1 (new MyObject()); 2 std::auto_ptr<MyObject> p2 = p1; // 试图将智能指针p2也指向p1 3 // p1会指向空 4 p2->DoSomething(); // 没问题 5 p1->DoSomething(); // 会出现问题
当试图做出数个auto_ptr共享一个内存空间的时候,会有智能指针被夺取控制权,所以auto_ptr的问题就是有可能出现内存问题,于时在C++11中被抛弃。
所以C++11搞出来三个更厉害更高效的智能指针,分别是shared_ptr,unique_ptr,weak_ptr。这三个智能指针各有各的特点:
首先是unique_ptr,特点就是每个智能指针不能被共享,任何企图共享的行为都会被编译器报错。例如Code02中,p2试图指向p1,如果p2和p1的类型都为unique_ptr的话,编译器直接会报错。在编译阶段就能阻止这种现象的发生,所以unique_ptr要比auto_ptr安全很多了。
然后是常用的shared_ptr,特点就是和unique_ptr的特点完全反过来,即完全可以被多个智能指针共享。
1 void f() 2 { 3 typedef std::shared_ptr<MyObject> MyObjectPtr; 4 MyObjectPtr p1; 5 6 { 7 MyObjectPtr p2(new MyObject()); 8 9 p1 = p2; // 分享指针 10 // 现在这片区域被两个智能指针所指向着 11 } 12 }
不仅如此,shared_ptr也有很多实用的函数和变量,例如use_count(),它可以找出目前这个智能指针所指向的区域一共有多少shared_ptr在指向着。并且,当一个shared_ptr结束其生命周期时,并不会释放资源,当这片区域的最后一个引用(即智能指针)结束生命周期后,才会释放掉这些资源。
shared_ptr仍然有缺点,即当两个对象的成员智能指针互相指向对方时,会造成一个无限循环的指向过程,导致这两个对象的use_count()等于无限大,导致这两片内存无法被释放(因为count为无限大,不可能为0)从而造成内存泄漏。为了避免这种情况,我们可以使用weak_ptr,这是最安全的智能指针。
以上是我的个人看法加上一些网上的参考代码结合而成的文章,是我的笔记,也希望能启发一下别人。
这篇关于C++智能指针的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享