c++ 复制控制和智能指针实现
2016-06-04 21:02
337 查看
1.复制控制场合
C++复制控制提供对象复制时的行为自定义,主要分如下三种a).复制构造函数
复制构造函数,顾名思义就是在复制对象时会调用的构造函数,很多时候隐式调用的,包含如下:[1].声明类对象时同时给一个初始化值,此时叫复制初始化
如
Class A;
Class B=A;
[2].函数形参为传值,返回值为传值时
如
void func(Class A);
Class func();
[3].容器初始化时,指明容器个数时,此时会先生成一个临时对象,然后将此对象复制给其他的对象
如
vector<Class> A(5);
[4].数组形式初始化时,会一一复制对应对象
如
Class A[] = {A1, A2, A3};
b).赋值重载函数
赋值时,对于一般的都是直接使用合成赋值函数。但是对于成员变量为指针、对象或复制时希望完成其他附加操作的均需自己来处理赋值行为。c).析构函数
最简单的就是自动释放成员指针指向的内存了。2.复制控制实现
如下为复制控制的实现class CCopyControl { public: CCopyControl(int nData=0); CCopyControl(const CCopyControl& c); //复制构造函数 CCopyControl& operator=(const CCopyControl& c); //赋值重载函数 ~CCopyControl(); //析构函数 private: int m_nData; int *m_pData; void CopyData(const CCopyControl& c); void DeleteData(); }; //默认构造函数 CCopyControl::CCopyControl( int nData/*=0*/ ) { m_nData = nData; m_pData = new int(nData); } //复制构造函数 CCopyControl::CCopyControl( const CCopyControl& c ) { CopyData(c); } //赋值重载函数 CCopyControl& CCopyControl::operator=( const CCopyControl& c ) { if (this != &c) { DeleteData(); CopyData(c); } return *this; } //析构函数 CCopyControl::~CCopyControl() { DeleteData(); } //复制数据 void CCopyControl::CopyData( const CCopyControl& c ) { this->m_nData = c.m_nData; this->m_pData = new int(c.m_nData); //深拷贝 } //删除数据 void CCopyControl::DeleteData() { if (!m_pData) { delete m_pData; m_pData = NULL; } }
需要注意点如下:
1.常见三种复制是一起出现的,即需要自定义一种复制行为时,往往另外两种也需要自定义
2.需要禁止复制时,必须显式地声明其复制构造函数为 private(其友元和成员依然可以复制)
3.如果要连友元和成员的复制也禁止,就可以声明一个private的复制构造函数但不对它进行定义。(如果复制类对象会提示编译错误,如果成员和友元尝试复制就会导致链接错误)
4.在实现时其实赋值重载函数是包含复制构造函数和析构函数功能的,此时可以将复制和析构功能单独做到两个私有函数中,如演示代码中的CopyData和DeleteData
3.智能指针实现
很自然想到,通过复制控制我们可以给指针包上一层壳,来管理指针对应内存的开辟和释放,这就是所谓的“智能指针”。可以看到前面演示时赋值过程指针为深拷贝,重新开辟了新的内存,复制的只是指针内容;但是为了实现智能指针,则必须共享指针,此时是浅拷贝,但是如果要实现自动释放内存的功能,此时需要在对象析构函数时释放内存,这样就存在多次释放的问题了,为此引入引用计数,只有引用计数为0时才真正释放内存。
下面是我实现的一个简单的智能指针类
template <class T> class CMySmartPtr { public: /*构造函数*/ CMySmartPtr(T* pT) { pCountT = new CCountT(pT); } CMySmartPtr() { pCountT = NULL;//默认指针为空 } /*复制控制*/ ~CMySmartPtr() { DeleteData(); } CMySmartPtr(const CMySmartPtr& p) { CopyData(p); } CMySmartPtr& operator=(const CMySmartPtr& p) { if (this != &p)//注意自身对自身赋值的情况 { DeleteData(); CopyData(p); } return *this; } /*指针*和->解引用*/ T& operator*() { return *(this->pCountT->pT); } T* operator->() { return this->pCountT->pT; } private: //装饰类,为待管理的指针增加引用计数 class CCountT { public: CCountT(T* pT) { this->pT = pT; this->nCount = 1; } ~CCountT() { delete pT; } T* pT; int nCount; }; //统一共享的指针,依靠引用计数来释放 private: CCountT *pCountT; void CopyData(const CMySmartPtr& p) { p.pCountT->nCount++; this->pCountT = p.pCountT; } void DeleteData() { if (pCountT && --pCountT->nCount==0) { delete pCountT; pCountT = NULL; } } };
这里注意如下几点:
1.创建一个私有类,专门用来包装实际指针pT,为其提供引用计数
2.注意赋值时需要考虑注意自身对自身赋值的情况
3.这里只是考虑了简单的单线程,多线程可能还存在问题
本文完整演示代码下载链接
原创,转载请注明来自http://blog.csdn.net/wenzhou1219
相关文章推荐
- C/C++之指针运算
- c++第七次实验
- C++中istream_iterator 与 ostream_iterator的用法
- 【C++ 学习】04 C & C++ 记录
- c++ string startwith方法使用
- c++第五次作业
- C++第七次实验——函数复习
- C/C++的前世今生
- OJ题 1019 逆输出
- 【Effective C++】为类设计new_handler
- c++第四次作业
- C++作业7
- c++第六次作业
- C++作业7
- C++第6次上机实验
- JAVA C# C/C++之比教学:编译机制
- 模板类中重载<<和>>操作符
- 《C++沉思录》——面向对象
- [置顶] Qt/C++ 模仿 360安全卫士 10.2版本
- C语言判断一个数是否是2的幂次方或4的幂次方