http://blog.csdn.net/xinpo66/article/details/8786057
用c++简单实现智能指针
什么是智能指针?答案相当简单;智能指针是聪明的普通指针。这是什么意思?实际上,智能指针是一些对象,表现出普通指针的功能但是比普通指针多做了一些事情。这些对象像普通指针一样灵活,并且管理对象有自己的优点(比如构造器和自动析构)。智能指针解决了普通指针的一些问题。
普通指针的问题。
我们使用C++语言中的指针,最常见的问题是什么?内存管理吧,请看下面的代码:
- char* pName = new char[1024];
- …
- SetName(pName);
- …
- …
- if(null != pName)
- {
- delete[] pName;
- }
下面写一个实际例子,先写一个叫做Person的类。
- class Person
- {
- int age;
- char* pName;
- public:
- Person(): pName(0),age(0)
- {
- }
- Person(char* pName, int age): pName(pName), age(age)
- {
- }
- ~Person()
- {
- }
- void Display()
- {
- printf("Name = %s Age = %d \n", pName, age);
- }
- void Shout()
- {
- printf("Ooooooooooooooooo");
- }
- };
下面是客户端代码使用Person类。
- void main()
- {
- Person* pPerson = new Person("Scott", 25);
- pPerson->Display();
- delete pPerson;
- }
现在我们来看这段代码,每当我创建一个指针,都要管理释放它。我要自动的释放它,智能指针可以。因此我们创建一个SP类来管理Person的对象,客户端的代码可以这样写:
- void main()
- {
- SP p(new Person("Scott", 25));
- p->Display();
- // Dont need to delete Person pointer..
- }
- void main()
- {
- SP p(new Person("Scott", 25));
- p->Display();
- // Dont need to delete Person pointer..
- }
注意:
1,我们创建了一个SP对象来管理Person的指针,当SP对象的作用域结束,会自动析构,它将释放Person的指针。
2,我们可以使用SP的对象p调用Display()函数,就像Person类的对象指针调用Display()函数,它的行为表现的像Person类的对象指针。
智能指针接口
智能指针表现出指针的行为,所以应该支持如下运算符:
- Dereferencing (operator
*
) - Indirection (operator
->
)
下面实现智能指针SP:
- class SP
- {
- private:
- Person* pData; // pointer to person class
- public:
- SP(Person* pValue) : pData(pValue)
- {
- }
- ~SP()
- {
- // pointer no longer requried
- delete pData;
- }
- Person& operator* ()
- {
- return *pData;
- }
- Person* operator-> ()
- {
- return pData;
- }
- };
这就是我们智能指针,当它的析构函数被调用时会释放Person类的对象指针。它也支持类似于指针的操作。
通用的智能指针
但是有个问题,我们智能控制Person类,也就是说每一种类型我们都要实现一个智能指针。我们可以使用模版使它通用。
- template < typename T > class SP
- {
- private:
- T* pData; // Generic pointer to be stored
- public:
- SP(T* pValue) : pData(pValue)
- {
- }
- ~SP()
- {
- delete pData;
- }
- T& operator* ()
- {
- return *pData;
- }
- T* operator-> ()
- {
- return pData;
- }
- };
- void main()
- {
- SP<Person> p(new Person("Scott", 25));
- p->Display();
- // Dont need to delete Person pointer..
- }
我们的智能指针这样就真的智能了吗?验证下面的代码:
- void main()
- {
- SP<Person> p(new Person("Scott", 25));
- p->Display();
- {
- SP<Person> q = p;
- q->Display();
- // Destructor of Q will be called here..
- }
- p->Display();
- }
这样就会存在一个问题:p和q关联到了Person类的相同对象指针,当q结束它的作用域时会释放Person类的对象指针,我们用p调用Display()函数会因为垂悬指针而失败。我们应该在不使用它的时候再释放,智能指针中引入计数便可解决。
计数器。
下面实现一个计数器的类RC.
- class RC
- {
- private:
- int count; // Reference count
- public:
- void AddRef()
- {
- // Increment the reference count
- count++;
- }
- int Release()
- {
- // Decrement the reference count and
- // return the reference count.
- return --count;
- }
- };
下面把计数器引入到我们的智能指针中:
- template < typename T > class SP
- {
- private:
- T* pData; // pointer
- RC* reference; // Reference count
- public:
- SP() : pData(0), reference(0)
- {
- // Create a new reference
- reference = new RC();
- // Increment the reference count
- reference->AddRef();
- }
- SP(T* pValue) : pData(pValue), reference(0)
- {
- // Create a new reference
- reference = new RC();
- // Increment the reference count
- reference->AddRef();
- }
- SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)
- {
- // Copy constructor
- // Copy the data and reference pointer
- // and increment the reference count
- reference->AddRef();
- }
- ~SP()
- {
- // Destructor
- // Decrement the reference count
- // if reference become zero delete the data
- if(reference->Release() == 0)
- {
- delete pData;
- delete reference;
- }
- }
- T& operator* ()
- {
- return *pData;
- }
- T* operator-> ()
- {
- return pData;
- }
- SP<T>& operator = (const SP<T>& sp)
- {
- // Assignment operator
- if (this != &sp) // Avoid self assignment
- {
- // Decrement the old reference count
- // if reference become zero delete the old data
- if(reference->Release() == 0)
- {
- delete pData;
- delete reference;
- }
- // Copy the data and reference pointer
- // and increment the reference count
- pData = sp.pData;
- reference = sp.reference;
- reference->AddRef();
- }
- return *this;
- }
- };
在看看客户端的代码:
- Collapse | Copy Code
- void main()
- {
- SP<PERSON> p(new Person("Scott", 25));
- p->Display();
- {
- SP<PERSON> q = p;
- q->Display();
- // Destructor of q will be called here..
- SP<PERSON> r;
- r = p;
- r->Display();
- // Destructor of r will be called here..
- }
- p->Display();
- // Destructor of p will be called here
- // and person pointer will be deleted
- }