数据结构开发(8):再论智能指针
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 最大程度的模拟了原生指针的行为
- 计数机制确保多个智能指针合法的指向同一片堆空间
- 智能指针只能用于指向堆空间中的内存
- 不同类型的智能指针不要混合使用
- 堆对象的生命周期由智能指针进行管理