【C++智能指针 auto_ptr】
《More Effective C++》ITEM M9他提到auto_ptr。说是当异常产生的时候。怎么释放为对象分配的堆内存,避免反复编写内存释放语句。
PS:这里书里面提到函数退出问题,函数退出会清理栈内存,无论是怎么正常退出还是异常退出(仅有一种例外就是当你调用 longjmp 时。Longjmp 的这个缺点是 C++领先支持异常处理的主要原因)。建立在此基础上我们才把对指针的删除操作封装到一个栈对象里面。
这样函数退出(异常或是正常)就会调用对象的析构函数,达到我们自己主动清理所封装指针指向的内存的目的。
作为新手。不是非常理解,记下来,学习学习。
PS:C++11已经不提倡用auto_ptr了,请看链接:http://www.cplusplus.com/reference/memory/auto_ptr/
Note: This class template is deprecated as of C++11. unique_ptr is
a new facility with a similar functionality, but with improved security (no fake copy assignments), added features (deleters)
and support for arrays. Seeunique_ptr for
additional information.
下面内容copy自:http://blog.sina.com.cn/s/blog_7708265a01010lyv.html
1. auto_ptr是什么?
auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者。一块内存不能同一时候被分给两个拥有者。
当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);
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
由于一块动态内存智能由一个智能指针独享,所以在拷贝构造或赋值时都会发生拥有权转移的过程。在此拷贝构造过程中,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 the object which ap1 point to: " << ap1.get() << endl;
输出例如以下:
the adress of p: 00481E00
the adress of ap1: 0012FF68
the adress of the object which ap1 point 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能够首先释放全部权
附上auto_ptr的实现代码:
namespace std
{
template<class T>
class auto_ptr
{
private:
T* ap;
public: // constructor & destructor ----------------------------------- (1)
explicit auto_ptr (T* ptr = 0) throw() : ap(ptr){} ~auto_ptr() throw()
{
delete ap;
} // Copy & assignment --------------------------------------------(2)
auto_ptr (auto_ptr& rhs) throw() :ap(rhs.release()) {}
template<class Y>
auto_ptr (auto_ptr<Y>& rhs) throw() : ap(rhs.release()) { } auto_ptr& operator= (auto_ptr& rhs) throw()
{
reset(rhs.release());
return *this;
}
template<class Y>
auto_ptr& operator= (auto_ptr<Y>& rhs) throw()
{
reset(rhs.release());
return *this;
} // Dereference----------------------------------------------------(3)
T& operator*() const throw()
{
return *ap;
}
T* operator->() const throw()
{
return ap;
} // Helper functions------------------------------------------------(4)
// value access
T* get() const throw()
{
return ap;
} // release ownership
T* release() throw()
{
T* tmp(ap);
ap = 0;
return tmp;
} // reset value
void reset (T* ptr=0) throw()
{
if (ap != ptr)
{
delete ap;
ap = ptr;
}
} // Special conversions-----------------------------------------------(5)
template<class Y>
struct auto_ptr_ref
{
Y* yp;
auto_ptr_ref (Y* rhs) : yp(rhs) {}
}; auto_ptr(auto_ptr_ref<T> rhs) throw() : ap(rhs.yp) { }
auto_ptr& operator= (auto_ptr_ref<T> rhs) throw()
{
reset(rhs.yp);
return *this;
}
template<class Y>
operator auto_ptr_ref<Y>() throw()
{
return auto_ptr_ref<Y>(release());
}
template<class Y>
operator auto_ptr<Y>() throw()
{
return auto_ptr<Y>(release());
}
};
}
版权声明:本文博客原创文章,博客,未经同意,不得转载。
【C++智能指针 auto_ptr】的更多相关文章
- 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 其 ...
- C++中的智能指针(auto_ptr)
实际上auto_ptr 仅仅是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势.使用它不必每次都手动调用delete去释放内存.当然有利也有弊,也不是全然完美的. 本 ...
- 【C++】智能指针auto_ptr简单的实现
//[C++]智能指针auto_ptr简单的实现 #include <iostream> using namespace std; template <class _Ty> c ...
- 智能指针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创建的动态内存,它是这块内存的拥有者,一块内存不能同一时候被分给两个拥有者.当 ...
随机推荐
- nginx简介(轻量级开源高并发web服务器:大陆使用者百度、京东、新浪、网易、腾讯、淘宝等)(并发量5w)(一般网站apache够用了,而且稳定)
nginx简介(轻量级开源高并发web服务器:大陆使用者百度.京东.新浪.网易.腾讯.淘宝等)(并发量5w)(一般网站apache够用了,而且稳定) 一.总结 1.在连接高并发的情况下,Nginx是A ...
- js进阶正则表达式实现过滤字符串(RegExp对象操作正则表达式)(正则:regular)(表达式:expression)
js进阶正则表达式实现过滤字符串(RegExp对象操作正则表达式)(正则:regular)(表达式:expression) 一.总结 1.str_replace:正则作用:高效快速匹配 2.break ...
- source insight totalcmd 中文目录
@echo off for /F "usebackq delims=" %%a in (`echo %1^^^|iconv -f utf-8 -t gb18030`) do ( s ...
- 如何安全退出多个Activity
我们在项目开发的时候可能会遇到安全退出应用的场景,如何能够安全退出多个Activity?网上有很多方法,如下: 1.抛异常退出 该方法通过抛异常,使程序Force Close.验证可以,但是,需要解决 ...
- Android 让文本输入框默认不获取焦点
项目中有个检索功能,页面上有个EditText输入框,打开页面后,焦点默认在EditText上,这样的话软键盘默认就会显示出来,占据大半个屏幕. 后来想办法将这个给去掉了,原先考虑着将焦点赋给页面上的 ...
- 数据结构与算法——常用数据结构及其Java实现
前言 仿佛一下子,2017年就快过去一半了,研一马上就要成为过去式了,我打算抓住研一的尾巴,好好梳理一下数据结构与算法,毕竟这些基础知识是很重要的嘛.所以准备在这里搞一个系列的文章,以期透彻. 本系列 ...
- ScrollView嵌套ListView问题
ScrollView嵌套ListView问题 导致Listview 第一主角 它是 Listview 的item 显示器的数量是不完全. 这是因为item 中间 Textview 话是太多的问题 一 ...
- Tower与DevCloud对比分析报告
1. 产品介绍 Tower是彩程设计公司出品的远程办公和团队协作工具,为小企业和小团队提供简单.靠谱的在线协作服务. DevCloud是集华为研发实践.前沿研发理念.先进研发工具为一体的研发云平台.D ...
- C++基础之字符数组和字符串
无意中发现了一个非常有意思的技术类型小品文系列,通过大牛指导菜鸟的方式,解说讲C++知识,有的非常基础却是开发中easy忽略的地方. [Elminster的专栏] http://blog.csdn.n ...
- C# 静态构造函数,静态变量执行顺序(升华版)
上篇 是基本语法基础下的执行顺序,包括继承这个维度下的执行顺序,我们可以依照的规律顺下来,下面我们看下一些摸不到头脑的情况 我们实验 一个 类中的方法 去调用另一个非继承类的情况, 我们主要看下 ...