C++智能指针管理类
1.程序员明确的进行内存释放
对于c++程序员,最头脑的莫过于对动态分配的内存进行管理了。c++在堆上分配的内存,需要程序员负责对分配的内存进行释放。但有时内存的释放看起来并不件很轻松的事,如下程序
void func() { int *p = new int(0); if(一些判断) { return; } p = new int(1); delete p; }
这个函数没有任何意义,只为说明问题。func函数至少有三处问题。1.一旦if的判断条件成立,就会立马执行返回语句。此时p所指向的内存将无法释放(这个新手一般都会犯的错误)。2. p = new int(1);语句,没有将原来分配在堆上的内存释放,造成原来那块内存永远不可能释放直到程序结束。3.这个问题并不是那么明显,假设func()函数的代码很长。
void func() { int *p = new int(0); ... delete p; }
在int *p = new int(0)和delete p之间有大量代码,而这中间的代码可能有代码已经执行过delete p,并且没有把p置0。此时p为悬挂指针。后面再执行delete p就会造成运行时错误。
2.一个类似于boost shared_ptr的智能指针管理类
下面是参照c++ primer及effective c++自己写的一个智能指针管理类。使用SmartPtr,就不再需要关心内存的释放问题了。
#ifndef SMARTPTR_INCLUDE_H #define SMARTPTR_INCLUDE_H #include <iostream> using namespace std; namespace commutil { template<typename T> class SmartPtr { public: SmartPtr(T *p = 0); SmartPtr(const SmartPtr &); SmartPtr &operator=(const SmartPtr &); ~SmartPtr(); T &operator *(); T *operator ->(); private: void decreaseRef(); T *m_p; int *m_useCnt; }; template<typename T> SmartPtr<T>::SmartPtr(T *p=0):m_p(p) { //调用此构造函数时,默认引用数为1 m_useCnt = new int(1); } template<typename T> SmartPtr<T>::SmartPtr(const SmartPtr &rhs) { //使用复制构造函数,创建新的对象,引用数加1 this->m_p = rhs.m_p; this->m_useCnt = rhs.m_useCnt; (*m_useCnt)++; } template<typename T> SmartPtr<T>::~SmartPtr() { decreaseRef(); } template<typename T> void SmartPtr<T>::decreaseRef() { if(--(*m_useCnt)==0) {//当引用数为0时,释放heap内存 delete m_useCnt; delete m_p; } } template<typename T> T &SmartPtr<T>::operator *() { //重载解引用符 return *m_p; } template<typename T> T *SmartPtr<T>::operator ->() { //重载 ->运算符,返回真实的对象指针 return m_p; } template<typename T> SmartPtr<T> &SmartPtr<T>::operator=(const SmartPtr &anotherPtr) { if(this==&anotherPtr) {//防止自赋值 return *this; } //使用赋值运算符,原来所指对象的引用数减1。 decreaseRef(); m_p = anotherPtr.m_p; m_useCnt = anotherPtr.m_useCnt; ++*m_useCnt;//指向新的对象,所指对象引用数加1 return *this; } } #endif
3.使用SmartPtr的案例分析
3.1第一个SmartPtr的实例
void func()
{
SmartPtr<int> autoPtr(new int(1));
}
在func中,定义了SmartPtr的一个对象autoPtr,并用new int(1)在堆上分配一块内存,将分配的内存首地址传给SmartPtr的构造函数。此时autoPtr的m_useCnt的值为1。当func执行完成时,autoPtr对象超出其作用域,调用autoPtr的析构函数。在析构函数中调用私有的decreaseRef()函数,在decreaseRef()中将autoPtr的m_useCnt所内存值减1;此时m_useCnt所指内存值为0,执行delete
m_useCnt;delete m_p;。至此在创建autoPtr对象时动态分配的内存被释放。
3.2带有return语句的SmartPtr
void func() { SmartPtr<int> autoPtr(new int(1)); if(判断条件) { return; } }
func()函数中的if判断条件成立时,执行return;语句后,autoPtr超出其作用范围,内存释放。分析见3.1
3.3 SmartPtr对象管理新的SmartPtr对象
SmartPtr<int> autoPtr1(new int(0)); SmartPtr<int> autoPtr2(new int(1)); autoPtr1 = autoPtr2;
执行autoPtr1 = autoPtr2,由于SmartPtr类重载了赋值运算符。实际执行的是SmartPtr的operator=()函数,在上面这个赋值语句中,先autoPtr1的m_useCnt所指内存值减1。此时m_useCnt所指内存值变为0,执行m_p所指内存释放。使用SmartPtr解决了1中所提的第二个问题。并且所有内存管理与释放工作都由SmartPtr进行,程序员不需要再关心什么时候进行内存释放。
3.4SmartPtr共享对象资源
与auto_ptr不同,SmartPtr使用引用计数机制保证多个SmartPtr对象可以管理同一个对象资源
void func() { SmartPtr<int> autoPtr1(new int(0)); SmartPtr<int> autoPtr2(autoPtr1); }
执行SmartPtr autoPtr2(autoPtr1)调用SmartPtr的拷贝构造函数,在拷贝构造函数中将autoPtr2的m_useCnt及m_p分别指向autoPtr1所指向的内存,再将m_useCnt的引用数加1。func()函数结束时,两次调用SmartPtr的析构函数,两次析构函数后引用数为0,删除m_useCnt,m_p所指内存。
3.5SmartPtr访问类成员函数
class A { public: void print() { cout<<"A"<<endl; } }; void func() { A *obj = new A(); obj->print(); delete obj; }
SmartPtr重载了->运算符,可以将SmartPtr对象像指针一样访问成员函数。
void func() { SmartPtr<A> autoPtr(new A()); autoPtr->print(); }
4.小结
SmartPtr类实现了内存对象”自管理”,使用SmartPtr程序员不再需要关心动态内存的释放问题。与shared_ptr不同,SmartPtr类只能管理指针类型的资源,并且SmartPtr不支持自定义的资源释放函数。
C++智能指针管理类的更多相关文章
- QT/C++插件式框架、利用智能指针管理内存空间的实现、动态加载动态库文件
QT.C++插件式框架.主要原理还是 动态库的动态加载. dlopen()函数.下面为动态加载拿到Plugininstance对应指针.void**pp=(void**)dlsym(handle,&q ...
- 《C++ Primer Plus》16.2 智能指针模板类
智能指针是行为类似于指针的类对象,单这种对象还有其他功能.本节介绍三个可帮助管理动态内存分配的智能指针类.先来看看需要哪些功能以及这些功能是如何实现的.请看下面的函数:void remodel(std ...
- [翻译]将智能指针用于C++的类成员
http://stackoverflow.com/questions/15648844/using-smart-pointers-for-class-members Question: I'm hav ...
- C11内存管理之道:智能指针
1.shared_ptr共享智能指针 std::shared_ptr使用引用计数,每个shared_ptr的拷贝都指向相同的内存,在最后一个shared_ptr析构的时候,内存才会释放. 1.1 基本 ...
- C++智能指针详解
本文出自http://mxdxm.iteye.com/ 一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最 ...
- C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常
shared_ptr和new结合使用 一个shared_ptr默认初始化为一个空指针.我们也可以使用new返回的指针来初始化一个shared_ptr: shared_ptr<double> ...
- 【M28】智能指针
1.什么是智能指针? 所谓智能指针就是,看起来,用起来,感觉起来都像原始指针,但是提供了更多功能. 2.使用智能指针取代原始指针,可以获得更多的控制权.如下: a.在构造和析构的时候,可以做一些事. ...
- 【转】C++ 智能指针详解
一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 ...
- 【STL学习】智能指针之shared_ptr
前面已经学习过auto_ptr,这里补充另外一种智能指针,比auto_ptr要更强力更通用的shared_ptr. shared_ptr 简介及使用选择 几乎所有的程序都需要某种形式的引用计数智能指 ...
随机推荐
- [c++基本语法]——构造函数初始化列表
c++构造函数初始化成员变量列表: #pragma once class Node { public: int data; // 权值 Node *parent; // 父节点 Node *left; ...
- sublime text常用插件
这个比较重要,不会装插件的时候找了好久 sublime text常用插件 1.插件的安装方法 第一种:用package control 这个是用来管理插件的,必备啊,安装package control ...
- Nginx简介
序言Nginx 是 lgor Sysoev 为俄罗斯访问量第二的 rambler.ru 站点设计开发的.从 2004 年发布至今,凭借开源的力量,已经接近成熟与完善.Nginx 功能丰富,可作为 HT ...
- 如何使用highmaps制作中国地图
如何使用highmaps制作中国地图 文章目录 Highmaps 所需文件 地图初始化代码 highmaps 渲染讲解 highmaps 中国各城市坐标的json文件 highmaps 线上DEMO ...
- WebForm中<%=%>与<%#%>的区别?
1<%=%>相当于Response.Write(),是输出变量的值 2<%#%>专门用于数据绑定,可以绑定一些变量或者数据源中的信息,中间绑定是数据源的条目,若想让它起作用,必 ...
- SQL—— 事务
SQL 事务: 1. 定义: 事务是作为单个逻辑单元执行的一系列操作. 多个操作作为一个整体向系统提交,要么执行.要么都不执行,事务是一个不可分割的工作逻辑单元.这特别适用于多用户同时操作的数据通信 ...
- android环境搭建—— 工欲善其事必先利其器
安卓开发环境配置: 准备软件 a) JDK 点击下载 b) adt-bundle-windows-x86-20140702.zip 点击下载 [sdk + 特定版本platform + e ...
- Yii2.0 查询(CRUD)
yii2使用中的一些基本的增删改查操作.以用户为例说明: User::find()->all(); //返回所有用户数据: User::findOne($id); //返回 主键 ...
- ubuntu屏幕分辨率问题
今天在ubuntu下工作时突然屏幕上下各出现了一个大概2厘米的黑条,感觉屏幕被横向拉长了,莫名其妙,开始以为简单的调整下分辨率就好了,在系统设置显示里面发现分辨率只有两个可选参数,并且对象为未知,由于 ...
- A4纸网页打印——宽高设置
一.在公制长度单位与屏幕分辨率进行换算时,必须用到一个DPI(Dot Per Inch)指标. 经过我仔细的测试,发现了网页打印中,默认采用的是96dpi,并非传闻的72dpi . A4纸张的尺寸是2 ...