資料結構開發(8):再論智慧指標
阿新 • • 發佈:2018-12-15
0.目錄
1.Pointer與SmartPointer
2.SharedPointer
3.小結
1.Pointer與SmartPointer
本節目標:
- 完成 Pointer 類的具體實現
- 完成 SmartPointer 類的具體實現
思考
- 使用智慧指標( SmartPointer )替換單鏈表( LinkList )中的原生指標是否可行?
問題出在哪裡?
- SmartPointer的設計方案
- 指標生命週期結束時主動釋放堆空間
- 一片堆空間最多隻能由一個指標標識
- 杜絕指標運算和指標比較
新的設計方案——是時候建立新的智慧指標了!
Pointer是智慧指標的抽象父類( 模板 ):
- 純虛解構函式
virtual ~Pointer() = 0;
- 過載
operator-> ()
- 過載
operator* ()
(在StLib中實現Pointer.h和SmartPointer.h)
Pointer.h
#ifndef POINTER_H #define POINTER_H #include "Object.h" namespace StLib { template <typename T> class Pointer : public Object { protected: T* m_pointer; public: Pointer(T* p = NULL) { m_pointer = p; } T* operator-> () { return m_pointer; } T& operator* () { return *m_pointer; } bool isNull() { return (m_pointer == NULL); } T* get() { return m_pointer; } }; } #endif // POINTER_H
SmartPointer.h
#ifndef SMARTPOINTER_H #define SMARTPOINTER_H #include "Pointer.h" namespace StLib { template <typename T> class SmartPointer : public Pointer<T> { public: SmartPointer(T* p = NULL) : Pointer<T>(p) { } SmartPointer(const SmartPointer<T>& obj) { this->m_pointer = obj.m_pointer; const_cast<SmartPointer<T>&>(obj).m_pointer = NULL; } SmartPointer<T>& operator= (const SmartPointer<T>& obj) { if( this != &obj ) { T* p = this->m_pointer; this->m_pointer = obj.m_pointer; const_cast<SmartPointer<T>&>(obj).m_pointer = NULL; delete p; } return *this; } ~SmartPointer() { delete this->m_pointer; } }; } #endif // SMARTPOINTER_H
main.cpp測試
#include <iostream>
#include "SmartPointer.h"
using namespace std;
using namespace StLib;
class Test : public Object
{
public:
Test()
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
int main()
{
SmartPointer<Test> sp = new Test();
SmartPointer<Test> spn;
spn = sp;
return 0;
}
執行結果為:
Test()
~Test()
2.SharedPointer
思考:
- 如何實現 SharedPointer 使得多個智慧指標物件可以指向同一片堆記憶體,同時支援堆記憶體的自動釋放?
本節目標:
- 完成 SharedPointer 類的具體實現
SharedPointer 設計要點:
- 類模板
- 通過計數機制( ref )標識堆記憶體
- 堆記憶體被指向時:ref++
- 指標被置空時:ref--
- ref == 0 時:釋放堆記憶體
- 通過計數機制( ref )標識堆記憶體
計數機制原理剖析:
SharedPointer 類的宣告:
智慧指標的比較:
- 由於 SharedPointer 支援多個物件同時指向一片堆空間;因此,必須支援比較操作!
(在StLib中實現SharedPointer.h)
改進Pointer.h
#ifndef POINTER_H
#define POINTER_H
#include "Object.h"
namespace StLib
{
template <typename T>
class Pointer : public Object
{
protected:
T* m_pointer;
public:
Pointer(T* p = NULL)
{
m_pointer = p;
}
T* operator-> ()
{
return m_pointer;
}
T& operator* ()
{
return *m_pointer;
}
const T* operator-> () const
{
return m_pointer;
}
const T& operator* () const
{
return *m_pointer;
}
bool isNull() const
{
return (m_pointer == NULL);
}
T* get() const
{
return m_pointer;
}
};
}
#endif // POINTER_H
SharedPointer.h
#ifndef SHAREDPOINTER_H
#define SHAREDPOINTER_H
#include <cstdlib>
#include "Pointer.h"
#include "Exception.h"
namespace StLib
{
template <typename T>
class SharedPointer : public Pointer<T>
{
protected:
int* m_ref; // 計數機制成員指標
void assign(const SharedPointer<T>& obj)
{
this->m_ref = obj.m_ref;
this->m_pointer = obj.m_pointer;
if( this->m_ref )
{
(*this->m_ref)++;
}
}
public:
SharedPointer(T* p = NULL) : m_ref(NULL)
{
if( p )
{
this->m_ref = static_cast<int*>((std::malloc(sizeof(int))));
if( this->m_ref )
{
*(this->m_ref) = 1;
this->m_pointer = p;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create SharedPointer object ...");
}
}
}
SharedPointer(const SharedPointer<T>& obj) : Pointer<T>(NULL)
{
assign(obj);
}
SharedPointer<T>& operator= (const SharedPointer<T>& obj)
{
if( this != &obj )
{
clear();
assign(obj);
}
return *this;
}
void clear() // 將當前指標置為空
{
T* toDel = this->m_pointer;
int* ref = this->m_ref;
this->m_pointer = NULL;
this->m_ref = NULL;
if( ref )
{
(*ref)--;
if( *ref == 0 )
{
free(ref);
delete toDel;
}
}
}
~SharedPointer()
{
clear();
}
};
template <typename T>
bool operator == (const SharedPointer<T>& l, const SharedPointer<T>& r)
{
return (l.get() == r.get());
}
template <typename T>
bool operator != (const SharedPointer<T>& l, const SharedPointer<T>& r)
{
return !(l == r);
}
}
#endif // SHAREDPOINTER_H
main.cpp測試
#include <iostream>
#include "SharedPointer.h"
using namespace std;
using namespace StLib;
class Test : public Object
{
public:
int value;
Test() : value(0)
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
int main()
{
SharedPointer<Test> sp0 = new Test();
SharedPointer<Test> sp1 = sp0;
SharedPointer<Test> sp2 = NULL;
sp2 = sp1;
sp2->value = 100;
cout << sp0->value << endl;
cout << sp1->value << endl;
cout << sp2->value << endl;
cout << (sp0 == sp2) << endl;
sp2.clear();
cout << (sp0 == sp2) << endl;
return 0;
}
執行結果為:
Test()
100
100
100
1
0
~Test()
智慧指標的使用軍規:
- 只能用來指向堆空間中的單個變數( 物件 )
- 不同型別的智慧指標物件不能混合使用
- 不要使用 delete 釋放智慧指標指向的堆空間
3.小結
- SharedPointer 最大程度的模擬了原生指標的行為
- 計數機制確保多個智慧指標合法的指向同一片堆空間
- 智慧指標只能用於指向堆空間中的記憶體
- 不同型別的智慧指標不要混合使用
- 堆物件的生命週期由智慧指標進行管理