题计
根据上编智能指针好文中counted_ptr.h,实现智指针。
智能指针就是一般指针的一个代理,实现了一般指针的所有功能,并能自动回收资源;
一种常用的实现方式是使用引用计数的方式;这里的关键是不同的智能指针的实例需要共享引用计数和真正的对象实例,在一个程序中全局共享资源的方式有全局变量(data段),堆对象(使用指针进行访问)(heap段),共享内存(也是在heap段);这里采用的是堆对象。
智能指针实现的方式
(下面代码按照该方式实现)
代码
#include <iostream>
class Data {
public:
Data(int data) : data(data){}
~Data() {
std::cout << "~Data(): " << data << std::endl;
}
int data;
};
template <class T>
class SmartPtr {
public:
// 明确/显示 构造,不支持 SmartPtr<Data> s = new T();
explicit SmartPtr(T* obj = nullptr) : counter(nullptr)
{
if (obj != nullptr) {
counter = new Counter(obj); // 创建引用计数对象,智能指针对象(指向相同对象)共有
}
}
// 智能指针对象析构时,引用计数对象--
~SmartPtr()
{
Release();
}
// 拷贝构造函数: 引用计数对象++
SmartPtr(const SmartPtr& smartPtr) {
//Release(); 本身一开始就是空的,不用对引用计数对象进行--
Acquire(smartPtr.counter);
}
// 赋值构造函数: 本对象应用计数先--,然后将应用计数对象指针指向赋值对象,并计数对象++
SmartPtr& operator=(const SmartPtr& smartPtr) {
if (this != &smartPtr) {
Release();
Acquire(smartPtr.counter);
}
return *this;
}
// 指针取值操作符
T& operator*() const throw()
{
return *counter->obj;
}
T* operator->() const throw()
{
return counter->obj;
}
// 取裸指针操作
T* Get() const throw()
{
return counter == nullptr ? nullptr : counter->obj;
}
// 求引用计数对象中的引用计数
int UseCount()
{
if (counter == nullptr) {
return 0;
} else {
return counter->refCount;
}
}
private:
// 引用计数对象,将对象和引用计数绑定在一起,不同的智能指针对象指向同一个引用计数对象
struct Counter {
Counter(T* obj = nullptr, int refCount = 1) : obj(obj), refCount(refCount){}
int refCount;
T* obj;
};
// 引用计数--
void Release()
{
if (counter) {
if (--counter->refCount == 0) {
delete counter->obj; // 释放真正的对象
delete counter; // 释放应用计数对象
counter = nullptr; // 赋空,防止dangling指针,悬挂指针
}
}
}
// 应用计数++
void Acquire(Counter* c) {
counter = c;
if (counter) {
counter->refCount++;
}
}
Counter* counter;
};
int main()
{
SmartPtr<Data> smartPtr1(new Data(1));
SmartPtr<Data> smartPtr2(new Data(2));
//SmartPtr<Data> smartPtr2(smartPtr1);
std::cout << "smartPtr1.UseCount: " << smartPtr1.UseCount() << std::endl;
std::cout << "smartPtr2.UseCount: " << smartPtr2.UseCount() << std::endl;
smartPtr1 = smartPtr2;
std::cout << "smartPtr1.UseCount: " << smartPtr1.UseCount() << std::endl;
std::cout << "smartPtr2.UseCount: " << smartPtr2.UseCount() << std::endl;
return 0;
}
运行结果:
smartPtr1.UseCount: 1
smartPtr2.UseCount: 1
~Data(): 1
smartPtr1.UseCount: 2
smartPtr2.UseCount: 2
~Data(): 2