【C++】智能指针
auto_ptr
auto_ptr是当前C++标准库中提供的一种智能指针。
auto_ptr在构造时获取某个对象的所有去(ownership),在析构时释放该对象。我们可以这样使用auto_ptr来提高代码安全性:
int* p = new int();
auto_ptr<int> ap(p);
从此我们不必关心应该何时释放p,也不必担心发生异常会有内存泄漏,这是因为auto_ptr的析构函数会执行指针的释放,而析构函数会在ap除了作用域以后执行。
auto_ptr的出现,主要是为了解决“被异常抛出时发生资源泄漏”的问题。即如果我们让资源在局部对象构造时分配,在局部对象析构时释放,这样即使在函数执行过程时发生异常退出,也能保证局部对象被析构从而保证资源被释放。
这里我们只有几点要注意:
1)因为auto_ptr析构的时候肯定会删除它所拥有的那个对象,所以两个auto_ptr不能同时拥有一个对象。像这样:
int* p = new int();
auto_ptr<int> ap1(p);
auto_ptr<int> ap2(p);
因为ap1与ap2都认为指针p是归它管的,在析构时都试图删除p,两次删除同一个对象的行为在C++标准中是未定义的。所以我们必须防止这样使用auto_ptr
2)考虑下面这样用法
int* pa = new int[];
auto_ptr<int> ap(pa);
因为auto_ptr的析构函数中删除指针用的是delete,而不是delete[],所以我们不应该用auto_ptr来管理一个数组指针。
与引用计数型智能指针不同的,auto_ptr要求对其“裸”指针的完全占用性。也就是说一个“裸“指针不能同时被两个以上的auto_ptr所拥有。那么,在拷贝构造或赋值操作时,我们必须做特殊的处理来保证这个特性。auto_ptr的做法是”所有权转移“,即拷贝或赋值的源对象失去对”裸“指针的所有权,所以,与一般的拷贝构造函数,赋值函数不同,auto_ptr的拷贝构造函数,赋值函数的参数为引用而不是常引用。当然,一个auto_ptr也不能同时拥有两个以上的”裸“指针,所以拷贝或赋值的目标对象将现释放期原来所拥有的对象。
这里的注意点是:
1)因为一个auto_ptr被拷贝或赋值后,其已经失去对原对象的所有权,这个时候,对这个auto_ptr的解引用操作是不安全的。如下:
int* p = new int();
auto_ptr<int> ap1(p);
auto_ptr<int> ap2 = ap1;
cout<<*ap1; //错误,此时ap1只剩下一个NULL指针在手了
这种情况较为隐藏的情形出现在将auto_ptr作为函数参数按值传递,因为在函数调用过程中在函数的作用域中会产生一个局部对象来接收传入的auto_ptr(拷贝构造),这样,传入的实参auto_ptr就失去了其对原对象的所有权,而原对象会在函数退出时被局部auto_ptr删除。如下:
void f(auto_ptr<int> ap) {cout<<*ap}
auto_ptr<int> ap1(new int());
f(ap1);
cout<<*ap1; //错误,经过f(ap1)函数调用,ap1已经不再拥有任何对象了
2)因为auto_ptr不具有值语义,所以auto_ptr不能被用在STL标准容器中。所谓值语义,是指符合以下条件的类型(假设有类A):
A a1;
A a2(a1);
A a3;
a3=a1;
那么:a2 == a1, a3==a1
很明显,auto_ptr不符合上述条件,STL标准容器要用到大量的拷贝赋值操作,并且假设其操作的类型符合以上条件。
shared_ptr
auto_ptr由于它的破坏性复制语义,无法满足标准容器对元素的要求,因而不能放在标准容器中。boost库中提供了一种新型的智能指针shared_ptr,它解决了在多个指针间共享对象所有权的问题,同时也满足容器对元素的要求,因而可以安全地放入容器中。
shared_ptr的作用同指针,但会记录有多少个shared_ptr共同指向同一个对象。这便是所谓的引用计数。一旦最后一个这个的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象就会被自动删除。这在非环形数据结构中防止资源泄漏很有帮助。
【C++】智能指针的更多相关文章
- enote笔记法使用范例(2)——指针(1)智能指针
要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- C++智能指针
引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...
- EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针
一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...
- 智能指针shared_ptr的用法
为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...
- 智能指针unique_ptr的用法
unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...
- 基于C/S架构的3D对战网络游戏C++框架_05搭建系统开发环境与Boost智能指针、内存池初步了解
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- C++ 引用计数技术及智能指针的简单实现
一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...
- C++11智能指针读书笔记;
智能指针是一个类对象,而非一个指针对象. 原始指针:通过new建立的*指针 智能指针:通过智能指针关键字(unique_ptr, shared_ptr ,weak_ptr)建立的指针 它的一种通用实现 ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
随机推荐
- UEditor和CKEditor配置上传图片,视频,附件
UEditor: http://blog.sina.com.cn/s/blog_8bb128230102v12x.html CKEditor:http://blog.sina.com.cn/s/blo ...
- !! 浅谈Java学习方法和后期面试技巧
浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...
- [转] 多线程 《深入浅出 Java Concurrency》目录
http://ifeve.com/java-concurrency-thread-directory/ synchronized使用的内置锁和ReentrantLock这种显式锁在java6以后性能没 ...
- JS_01_入门学习
01:编写js文件:JavaScript_01.js // JavaScript Document //1.利用JavaScript来输出文字 <script type="text/j ...
- 使用Ef查询出现的问题The cast to value type 'System.Boolean' failed because the materialized value is null.的解决方法
把值类型的系统.布尔的失败是因为物化值是null.结果类型的泛型参数或查询必须使用可空类型. 解决方法: 请确保你查询中的字段值不为空或者做为空判断
- 「thunar」给thunar增加搜索文件功能
1.安装catfish sudo apt-get install catfish 2.配置thunar,添加[自定义动作] 打开 Thunar 后,点击 Edit -> Configure cu ...
- yii2获取登陆的用户名
yii2获取登陆的用户名: yii::$app->user->identity->username; 判断用户名是否登陆 if(Yii::$app->user->isGu ...
- php file_get_contents与curl性能比较
1.fopen /file_get_contents 每次请求都会重新做DNS查询,并不对 DNS信息进行缓存.但是CURL会自动对DNS信息进行缓存.对同一域名下的网页或者图片的请求只需要一次DNS ...
- Swift数据类型简介
用 Swift 编写 iOS 和 OS X 应用将是一场美妙的体验,Swift 之后也会不断开发新特性和兼容性. Swift 提供了与C.Objective-C的相似的基础数据类型,包含整数Int,浮 ...
- 背包问题(Knapsack problem)采用动态规划求解
问题说明: 假设有一个背包的负重最多可达8公斤,而希望在背包中装入负重范围内可得之总价物品,假设是水果好了,水果的编号.单价与重量如下所示:0李子4KGNT$45001苹果5KGNT$57002橘子2 ...