1、问题的提出
先看下面的例子:
class CText
{
public:
CText(int *&ptr):m_ptr(ptr)
{
}
~CText()
{
delete m_ptr;
}
private:
int *m_ptr;
};
int FunText()
{
int *ptr = new int;
CText CText1(ptr);
CText CText2(ptr);
return 0;
}
在函数FunText()中,类的两个对象共用了new出来的指针ptr。当函数运行开始时,调用两次构造函数;退出运行时,调用两次析构函数,而在第一次调用时已经delete ptr,因而第二次调用时将会出现错误。
以上例子说明,当类中有指针成员时,必须明确何时才是操作delete指针的时机。智能指针能够解决上述问题。
2、智能指针的原理
前面的例子运行时出现的错误系第二次析构时“无ptr可delete”所致。为解决这个问题,我们可以这样设想:定义一个计数变量int counter = 0,每次调用构造函数时,counter加1,调用析构函数时,counter减1。当counter等于0时,delete ptr。这样在函数退出时就不会有错误了。这种实现技术称之为引用计数。
智能指针需要运用引用计数技术。当然,这里就不再是定义计数变量那么简单了。依据C++的封装性,我们定义一个计数器类CCounter,负责对计数变量的操作。
class CCounter
{
public:
CCounter();
~CCounter();
public:
void AddCounter();
void DecCounter();
private:
UINT m_unCounter;
};
应用智能指针,其实就是建立一个智能指针类CSmartPointer。CSmartPointer将CCouter与CSmartPointer对象相关联,CCouter负责记录有多少个CSmartPointer对象共用同一指针。
template <class T>
class CSmartPointer
{
public:
CSmartPointer(T *);
CSmartPointer(const CSmartPointer<T> & );
CSmartPointer<T> &operator=(const CSmartPointer<T> &);
~CSmartPointer();
private:
T *m_pointer;
};
类CSmartPointer负责如下功能:
◆ 创建对象时,初始化类指针成员并调用AddCounter();
◆ 对象作为另一对象的副本而创建时,拷贝指针并调用AddCounter();
◆ 对对象进行赋值时,赋值运算符左边对象调用关联的DecCounter(),拷贝指针后,赋值运算符右边对象调用关联的AddCounter()。
◆ 调用析构函数,析构函数调用DecCounter()。
3、代码实现
类CCounter定义与实现:
//CCounter.h
#ifndef _CCOUNTER_H_
#define _CCOUNTER_H_
class CCounter //要使用智能指针的类须继承该类
{
public:
CCounter();
~CCounter();
public:
void AddCounter();
void DecCounter();
private:
UINT m_unCounter;
};
#endif
//CCounter.cpp
#include"CCounter.h"
CCounter::CCounter():m_unCounter(0)
{
}
CCounter::~CCounter()
{
assert(0 == m_unCounter);
}
void CCounter::AddCounter()
{
m_unCounter++;
}
void CCounter::DecCounter()
{
m_unCounter--;
assert(m_unCounter >= 0);
if (m_unCounter == 0)
{
delete this;
}
}
模板类CSmartPointer的定义与实现:
//CSmartPointer.h
#include"CCounter.h"
template <class T>
class CSmartPointer
{
public:
CSmartPointer(T *);
CSmartPointer(const CSmartPointer<T> &);
CSmartPointer<T> &operator=(const CSmartPointer<T> &);
~CSmartPointer();
private:
T *m_pointer;
};
template <class T>
CSmartPointer<T>::CSmartPointer(T *pointer = NULL):m_pointer(pointer)
{
if (NULL != m_pointer)
{
m_pointer->AddCounter();
}
}
template <class T>
CSmartPointer<T>::CSmartPointer(const CSmartPointer<T> &refSP)
{
if (NULL != refSP.m_pointer)
{
m_pointer = refSP.m_pointer;
m_pointer->AddCounter();
}
}
template <class T>
CSmartPointer<T> &CSmartPointer<T>::operator =(const CSmartPointer<T> &refSP)
{
if (this != &refSP) //不是本身
{
if (NULL != m_pointer)
{
m_pointer->DecCounter();
}
m_pointer = refSP.m_pointer;
if (NULL != m_pointer)
{
m_pointer->AddCounter();
}
}
}
template <class T>
CSmartPointer<T>::~CSmartPointer()
{
if (NULL != m_pointer)
{
m_pointer->DecCounter();
}
}
则可在主函数main()中,编写如下代码:
// main.cpp
#include" CSmartPointer.h"
class CText:public CCounter
{
public:
CText(int *&ptr):m_ptr(ptr)
{
}
~CText()
{
delete m_ptr;
}
private:
int *m_ptr;
};
int main()
{
CText *pCText = new CText;
CSmartPointer<CText> p1CSmartPointer(pCText);
CSmartPointer<CText> p2CSmartPointer(pCText);
CSmartPointer<CText> p3CSmartPointer(p2CSmartPointer);
return 0;
}