C++中的智能指针(auto_ptr)
实际上auto_ptr 仅仅是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势。使用它不必每次都手动调用delete去释放内存。当然有利也有弊,也不是全然完美的。
本文从以下的8个方面来总结auto_ptr使用的大部分内容。
1. auto_ptr是什么?
auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同一时候被分给两个这样拥有者(auto_ptr)。
当auto_ptr对象生命周期结束时。其析构函数会将auto_ptr对象拥有的动态内存自己主动释放。即使发生异常,通过异常的栈展开过程也能将动态内存释放。auto_ptr不支持new 数组。
2. auto_ptr须要包括的头文件?
#include <memory>
3. 初始化auto_ptr对象的方法?
1) 构造函数
1] 将已存在的指向动态内存的普通指针作为參数来构造
int* p = new int(33);
auto_ptr<int> api(p);
这样在api对象的生命周期结束的时候。会调用自身的析构函数,并delete来释放拥有的内存,这样我们就不须要写以下的代码:
delete p;
2] 直接构造智能指针
auto_ptr< int > api( new int( 33 ) );
2) 拷贝构造
利用已经存在的智能指针来构造新的智能指针
auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );
auto_ptr< string > pstr_auto2(pstr_auto ); //利用pstr_auto来构造pstr_auto2
由于auto_ptr智能指针仅仅能独享一块动态内存,所以在拷贝构造或赋值时都会发生拥有权的转移。
在此拷贝构造过程中,pstr_auto将失去对字符串内存的全部权,而pstr_auto2将其获得。
pstr_auto2负责内存的自己主动销毁。
3) 赋值
利用已经存在的智能指针来构造新的智能指针
auto_ptr< int > p1( new int( 1024 ));
auto_ptr< int > p2( new int( 2048 ));
p1 = p2;
在赋值之前。由p1 指向的对象被删除。赋值之后。p1 拥有int 型对象的全部权。该对象值为2048。 p2 不再被用来指向该对象。
4. 空的auto_ptr 须要初始化吗?
通常的指针在定义的时候若不指向不论什么对象,我们用Null给其赋值。
对于智能指针,由于构造函数有默认值0,我们能够直接定义空的auto_ptr例如以下:
auto_ptr< int >p_auto_int; //不指向不论什么对象
5. 防止两个auto_ptr对象拥有同一个对象(一块内存)
由于auto_ptr的全部权独有。不能共享动态分配的内存。所以以下的代码会造成混乱。
int* p = new int(0);
auto_ptr<int> ap1(p);
auto_ptr<int> ap2(p);
由于ap1与ap2都觉得指针p是归它管的,在析构时都试图删除p, 两次删除同一个对象的行为在C++标准中是没有定义的。所以我们必须防止这样使用auto_ptr。
6. 警惕智能指针作为參数!
1) 按值传递时,函数调用过程中在函数的作用域中会产生一个局部对象来接收传入的auto_ptr(拷贝构造)。这样。传入的实參auto_ptr就失去了其对原对象的全部权,而该对象会在函数退出时被局部auto_ptr删除。例如以下例:
void f(auto_ptr<int> ap)
{
cout<<*ap;
}
auto_ptr<int> ap1(new int(0));
f(ap1);
cout<<*ap1; //错误,经过f(ap1)函数调用,ap1已经不再拥有不论什么对象了。
2) 出入的是引用或指针时,不会存在上面的拷贝过程。
但我们并不知道在函数中对传入的auto_ptr做了什么。假设其中某些操作使其失去了对对象的全部权。那么这还是可能会导致致命的运行期错误。
结论:const reference是智能指针作为參数传递的底线。
7. auto_ptr不能初始化为指向非动态内存
原因非常easy。delete 表达式会被应用在不是动态分配的指针上这将导致没有定义的程序行为。
8. auto_ptr经常使用的成员函数
1) get()
返回auto_ptr指向的那个对象的内存地址。例如以下例:
int* p = new int(33);
cout << "the adress of p:"<< p << endl;
auto_ptr<int> ap1(p);
cout << "the adress of ap1:" << &ap1 << endl;
cout << "the adress of theobject which ap1 point to: " << ap1.get() << endl;
输出例如以下:
the adress of p: 00481E00
the adress of ap1: 0012FF68
the adress of the object which ap1point to: 00481E00
第一行与第三行同样,都是int所在的那块内存的地址。
第二行是ap1这个类对象本身所在内存的地址。
2) reset()
又一次设置auto_ptr指向的对象。
类似于赋值操作,但赋值操作不同意将一个普通指针指直接赋给auto_ptr,而reset()同意。例如以下例:
auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );
pstr_auto.reset( new string("Long -neck" ) );
在样例中。重置前pstr_auto拥有"Brontosaurus"字符内存的全部权,这块内存首先会被释放。之后pstr_auto再拥有"Long -neck"字符内存的全部权。
注:reset(0)能够释放对象。销毁内存。
3) release()
返回auto_ptr指向的那个对象的内存地址,并释放对这个对象的全部权。
用此函数初始化auto_ptr时能够避免两个auto_ptr对象拥有同一个对象的情况(与get函数相比)。
样例例如以下:
auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );
auto_ptr< string > pstr_auto2(pstr_auto.get() ); //这是两个auto_ptr拥有同一个对象
auto_ptr< string > pstr_auto2(pstr_auto.release() ); //release能够首先释放全部权
C++中的智能指针(auto_ptr)的更多相关文章
- 智能指针类模板(上)——STL中的智能指针
智能指针类模板智能指针本质上就是一个对象,它可以像原生指针那样来使用. 智能指针的意义-现代C++开发库中最重要的类模板之一-C++中自动内存管理的主要手段-能够在很大程度上避开内存相关的问题 1.内 ...
- C++中的智能指针类模板
1,智能指针本质上是一个对象,这个对象可以像原生的指针一样使用,因为智能指 针相关的类通过重载的技术将指针相关的操作符都进行了重载,所以智能指针对象可以像原生指针一样操作,今天学习智能指针类模板,通过 ...
- C++智能指针(auto_ptr)详解
智能指针(auto_ptr) 这个名字听起来很酷是不是?其实auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,但也有其局限.本文总结的8个问题足 ...
- 自己动手实现智能指针auto_ptr
面试的时候,我们经常会被问到如何自己动手实现智能指针auto_ptr.今天我就一边参考STL库中的源代码,一边将auto_ptr的实现敲一遍. auto_ptr归根到底是一个模版类,那么这个类要实现哪 ...
- C++ 智能指针auto_ptr
template<class T> class auto_ptr { public: ); // Item M5 有“explicitfor”// 的描述 template<clas ...
- 关于智能指针auto_ptr
智能指针auto_ptr和shared_ptr也是面试中经常被问到的一个 感觉看auto_ptr的源码反而更加容易理解一些,因为源码的代码量并不大,而且比较容易理解. 本篇主要介绍auto_ptr 其 ...
- 智能指针auto_ptr & shared_ptr
转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...
- C++智能指针 auto_ptr
C++智能指针 auto_ptr auto_ptr 是一个轻量级的智能指针, 定义于 memory (非memory.h)中, 命名空间为 std. auto_ptr 适合用来管理生命周期比较短或者不 ...
- C++智能指针--auto_ptr指针
auto_ptr是C++标准库提供的类模板,头文件<memory>,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同一时候被分给两个拥有者.当 ...
随机推荐
- Objective-C浅拷贝和深拷贝
浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间 如: char* str = (char*)malloc(100);char* str2 = str; 浅拷贝只是对对象的简单拷贝 ...
- Gimp制作圆角透明图片
用蒙版制作圆角透明图片,步骤如下: 1,用Gimp(2.8版本)打开图片 2,在图层窗口右键当前图层创建蒙版 3,选择蒙版类型黑色(全透明) 4,结果如下 5,用圆角矩形选择工具选择图片,设置圆角半径 ...
- Ants(思维)
Ants Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 12893 Accepted: 5637 Description ...
- SGU 202 The Towers of Hanoi Revisited (DP+递归)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题意 :n个圆盘,m个柱子的汉诺塔输出步骤. ht ...
- ubuntu14.04LTS ruby on rails 开发环境
小弟初学 Ruby,也没用过Linux. 在网上搜了好多关于开发环境的配置的文章,但总是和实际有点出入,找了N遍文章后,终于找到最简环境安装配置方法,分享下 推荐用 Ubuntu,感觉对于习惯用Win ...
- Extjs 3.0 htmleditor实现插入图片功能
首先感谢前辈们的无私奉献.贴出参考地址 http://zhidao.baidu.com/link?url=Q0ZM405OFNy_xAHSut9TepRJxgXCxFayQttrQz1N82dlA1_ ...
- STL之vector(向量)
C++编程语言中有一种叫做Vector的应用方法,它的作用在实际编程中是非常重要的,这里详细介绍一下C++ Vector的相关应用技巧及基本内容: Construct vector #include ...
- Flask中全局变量的实现
我们都知道在Flask中g,request,session和request是作为全局对象来提供信息的,既然是全局的又如何保持线程安全呢,接下来我们就看看flask是如何做到这点的.在源码中的ctx.p ...
- ASP.NET PipeLine #Reprinted#
从ASP.NET 1.0 起,相比于ASP中的COM, PipeLine 就是一项重大的改进. ASP.NET 时代的管道模型究竟是怎么样的? 我们能接触到的四个最重要的概念就是HttpApplica ...
- 【xcode】错误之Could not launch "" failed to get the task for process
http://blog.csdn.net/teng_ontheway/article/details/8467932 在Xcode下编译工程正常,在模拟器下运行正常,最后在真机上运行的时候出现了如下错 ...