条款13:关于文中多次提及的auto_ptr和shared_ptr
2015-10-03 09:36
423 查看
标题中提到的auto_ptr和shared_ptr以及unique_ptr都是智能指针,其中auto_ptr是C++98提供的解决方案,后两个是C++11提供的另外两种解决方案。
智能指针是行为类似于指针的类对象,但我们一般用他们来管理动态内存分配的智能指针模板。
智能指针模板都定义了类似指针的对象,可以将new获得(直接或间接)的地址赋给这种对象,当智能指针过期时,其析构函数将使用delete来释放内存。因此,如果将new返回的地址赋给这种对象,将无需记住稍后释放这些内存:在智能指针过期时,这些内存将自动被释放。
1.智能指针的使用
shared_ptr与unique_ptr和auto_ptr的使用方法类似。
2.智能指针的隐式转换和显式转换
模板auto_ptr包含如下构造函数:
3.智能指针的注意事项
1)全部三种智能指针都应避免一点:
错误原因:pvac过期时,程序将把delete运算符用于非堆内存。(堆内存是什么鬼?)
所谓堆内存,是区别于栈区、全局数据区和代码区的另一个内存区域。该区允许程序运行时动态申请某个大小的内存空间。
2)auto_ptr的不足
先看下面赋值语句:
如果ps和vocation是常规指针,则两个指针将指向同一个string 对象。这是不能接受的,因为程序将试图删除同一个对象两次---------一次是ps过期时,另一次是vocation过期时。要避免这种问题,方法有很多。
智能指针是行为类似于指针的类对象,但我们一般用他们来管理动态内存分配的智能指针模板。
智能指针模板都定义了类似指针的对象,可以将new获得(直接或间接)的地址赋给这种对象,当智能指针过期时,其析构函数将使用delete来释放内存。因此,如果将new返回的地址赋给这种对象,将无需记住稍后释放这些内存:在智能指针过期时,这些内存将自动被释放。
1.智能指针的使用
#include <iostream> #include <memory> using namespace std; void demo1() { double *pd=new double; //为pd和一个double值分配存储空间,保存地址 *pd=25.5; //将值复制到动态内存中 return; //删除pd,值被保存在动态内存中 } void demo2() { auto_ptr<double> *ap(new double); //为ap和一个double值分配存储空间,保存地址 *ap=25.5; //将值复制到动态内存中 return; //删除ap,ap的析构函数释放动态内存 }
shared_ptr与unique_ptr和auto_ptr的使用方法类似。
#include <iostream> #include <memory> #include <string> class Report { private: std::string str; public: Report(const std::string s) :str(s) { std::cout << " Object created!" << std::endl; } ~Report() { std::cout << "Object deleted!" << std::endl; } void comment() const { std::cout << str << std::endl; } }; int main() { { //作用域 std::auto_ptr<Report> ps(new Report("using auto_ptr")); ps->comment(); } { //作用域 std::shared_ptr<Report> ps(new Report("using shared_ptr")); ps->comment(); } { //作用域 std::unique_ptr<Report> ps(new Report("using unique_ptr")); ps->comment(); } return 0; }
2.智能指针的隐式转换和显式转换
模板auto_ptr包含如下构造函数:
template<class X> class auto_ptr { public: explicit auto_ptr(X* p = 0) throw(); ... };该构造函数是explicit构造函数,将指针作为参数,因此不能自动将指针转换为只能指针对象:
shared_ptr<double> pd; double *p_reg=new double; pd=p_reg;上面写法就是传说中的隐式转换,这是不允许的。若进行显式转换,则可以:
pd=shared_ptr<double> (p_reg)下面的隐式转换和显式转换也要注意:
shared_ptr<double> pshared=p_reg; //不允许(隐式转换) shared_ptr<double> pshared(p_reg); //允许(显式转换)
3.智能指针的注意事项
1)全部三种智能指针都应避免一点:
string vacation("I wandered lonely as a cloud."); shared_ptr<string> pvac(&vacation); //错误
错误原因:pvac过期时,程序将把delete运算符用于非堆内存。(堆内存是什么鬼?)
所谓堆内存,是区别于栈区、全局数据区和代码区的另一个内存区域。该区允许程序运行时动态申请某个大小的内存空间。
2)auto_ptr的不足
先看下面赋值语句:
auto_ptr<string> ps (new string("test")); auto_ptr<string> vocation; vocation=ps;
如果ps和vocation是常规指针,则两个指针将指向同一个string 对象。这是不能接受的,因为程序将试图删除同一个对象两次---------一次是ps过期时,另一次是vocation过期时。要避免这种问题,方法有很多。
//1.定义赋值运算符,使之执行深复制,这样两个指针将指向不同的对象,其中一个对象是另一个对象的副本。 //2.建立所有权概念,对于特定的对象,只能有一个只能指针可以拥有它,这样只有拥有对象的智能指针的析构函数会删除该对象。这就是auto_ptr和unique_ptr的策略,但unique_ptr的策略更严格。 //3.创建智能更高的指针,跟踪引用特定对象的智能指针数,这称为引用计数。仅当最后一个指针过期时才调用delete。这是shared_ptr采用的策略。
相关文章推荐
- 编码之道:取个好名字很重要
- 杂类未分类
- JS学习笔记
- 作为一个新人,如何学习嵌入式Linux?
- HDU 2955 Robberies(01背包问题)
- 【设计前沿】设计心理学
- First Bad Version【278】
- tar命令使用方法
- mysql大数据高并发处理
- 马哥运维笔记----3
- 毕业两年的我
- spark 日志分析
- 1031. Hello World for U (20)
- ucGUI学习笔记之对话框
- poj2689
- DirectX11 点光
- ios 开发学习 :多线程之GCD的使用指南
- 关于工作量估算,所有你知道的和你不知道
- poj2689
- 128. Longest Consecutive Sequence (List, Queue)