題計
根據上編智能指針好文中counted_ptr.h,實現智指針。
智能指針實現的方式
(下面代碼按照該方式實現)
代碼
#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