使用c++实现一个智能指针,代码如下:
template<class T>
class SmartPtr
{
private:
T* dataPtr;
void decrRef()
{
//只有引用计数为0时才会释放,否则会引起多次释放
if (--*countPtr == 0)
{
delete dataPtr;
delete countPtr;
}
}
public:
size_t* countPtr;
SmartPtr(T* p)
{
dataPtr = p;
countPtr = new size_t(1);
}
SmartPtr(const SmartPtr<T> &src)
{
dataPtr = src.dataPtr;
++*(src.countPtr);
countPtr = src.countPtr;
}
SmartPtr<T>& operator = (const SmartPtr<T>& src)
{
decrRef();
++*(src.countPtr);
dataPtr = src.dataPtr;
countPtr = src.countPtr;
return *this;
}
~SmartPtr<T>()
{
decrRef();
std::cout << "SmartPtr: Destructor" << std::endl;
}
T operator * ()
{
if (dataPtr)
return *dataPtr;
throw std::runtime_error("dereference of NULL pointer");
}
T* operator -> ()
{
if (dataPtr)
return dataPtr;
throw std::runtime_error("access through NULL pointer");
}
};
需要注意的是为了使多个智能指针对象共享同一块数据对象内存和对象引用计数,dataPtr和countPtr必须使用指针。
测试一下代码:
#include "pch.h"
#include <iostream>
class TestClass
{
public:
int data;
int *ptr = NULL;
TestClass(int& n, int& m)
{
data = n;
ptr = new int(m);
}
~TestClass()
{
std::cout << "TestClass: Destructor" << std::endl;
if (ptr)
{
delete ptr;
ptr = NULL;
}
}
};
int main()
{
int n = 1, m = 2;
int i = 3, j = 4;
int a = 5, b = 6;
SmartPtr<TestClass> ptr1(new TestClass(n, m));
SmartPtr<TestClass> ptr2(new TestClass(i, j));
SmartPtr<TestClass> ptr3(new TestClass(a, b));
std::cout << "ptr2的引用计数为: " << *(ptr2.countPtr) << std::endl;
ptr1 = ptr2;
std::cout << "ptr2的引用计数为: " << *(ptr2.countPtr) << std::endl;
ptr1 = ptr3;
std::cout << "ptr2的引用计数为: " << *(ptr2.countPtr) << std::endl;
system("PAUSE ");
}
结果如下:
ptr2的引用计数为: 1
TestClass: Destructor
ptr2的引用计数为: 2
ptr2的引用计数为: 1
请按任意键继续. . .
SmartPtr: Destructor
TestClass: Destructor
SmartPtr: Destructor
TestClass: Destructor
SmartPtr: Destructor
注意c++标准库自带的智能指针std::auto_ptr并不是使用引用计数方法实现的,它仅仅起到auto_ptr析构时释放数据对象的功能,因此不能使两个auto_ptr对象都指向同一个数据对象,否则两个auto_ptr对象析构时会释放两次数据对象。同理不能按值传参auto_ptr对象,否则临时对象拷贝会造成多个auto_ptr对象指向同一数据对象。