1、再论智能指针
思考
使用智能指针(SmartPointer)替换单链
表(LinkList)中的原生指针是否可行?
LinkList.h
#ifndef LINKLIST_H
#define LINKLIST_H
#include"List.h"
#include"Exception.h"
#include"SmartPointer.h"
namespace DTLib
{
template <typename T>
class LinkList : public List<T>
{
protected:
struct Node : public Object
{
T value;
SmartPointer<Node> next;
};
mutable struct : public Object //保证内存布局一致
{
char reserved[sizeof(T)]; //木有实际作用,仅仅占空间,保证内存布局和Node一样
SmartPointer<Node> next;
}m_header;
int m_length;
SmartPointer<Node> m_current;
int m_step;
Node* position(int i) const
{
SmartPointer<Node> ret = reinterpret_cast<Node*>(&m_header);
for(int p=0;p<i;p++)
{
ret = ret->next;
}
return ret.get();
}
virtual Node* create()
{
return new Node();
}
virtual void destroy(Node* pn)
{
delete pn;
}
public:
LinkList()
{
m_header.next = NULL;
m_length = 0;
m_step = 1;
m_current = NULL;
}
bool insert(int i,const T& e)
{
bool ret = (0 <= i)&&(i <= m_length);
if(ret)
{
SmartPointer<Node> node = create();
if( node.isNull() )
{
SmartPointer<Node> current = position(i);
node->value = e;
node->next = current->next;
current->next = node;
m_length++;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to insert new element ...");
}
}
return ret;
}
bool insert(const T& e)
{
return insert(m_length,e);
}
bool remove(int i)
{
bool ret = (0 <= i)&&(i < m_length);
if(ret)
{
SmartPointer<Node> current = position(i);
SmartPointer<Node> toDel = current->next;
if(m_current.get() == toDel.get())
{
m_current = toDel->next; //游标指向下一个数据元素即可
}
current->next = toDel->next;
m_length--;
// destroy(toDel);
}
return ret;
}
bool set(int i,const T& e)
{
bool ret = (0 <= i)&&(i < m_length);
if(ret)
{
position(i)->next->value = e;
}
return ret;
}
T get(int i) const
{
T ret;
if(get(i,ret))
{
return ret;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsExpception,"Invalid parameter i to get element ...");
}
return ret;
}
bool get(int i,T& e) const
{
bool ret = (0 <= i)&&(i < m_length);
if(ret)
{
e = position(i)->next->value; //position 为 const 成员函数
}
return ret;
}
int find(const T& e) const
{
int ret = -1;
int i = 0;
SmartPointer<Node> node = m_header.next;
while( node.isNull() )
{
if(node->value == e)
{
ret = i;
break;
}
else
{
node = node->next;
i++;
}
}
return ret;
}
int length() const
{
return m_length;
}
void clear()
{
while( m_header.next.isNull() )
{
SmartPointer<Node> toDel = m_header.next;
m_header.next = toDel->next;
m_length--;
// destroy(toDel);
}
}
bool move(int i,int step = 1)
{
bool ret = (0 <= i)&&(i < m_length)&&(step > 0);
if(ret)
{
m_current = position(i)->next;
m_step = step;
}
return ret;
}
bool end()
{
return ( m_current.isNull());
}
T current()
{
if(!end()) //if( m_current != NULL )
{
return m_current->value;
}
else
{
THROW_EXCEPTION(InvalidParameterException,"No value at current position ...");
}
}
bool next()
{
int i = 0;
while((i < m_step) && !end())
{
m_current = m_current->next;
i++;
}
return (i == m_step);
}
~LinkList()
{
clear(); //构造函数析构函数不会发生多态,destroy调用的父类
}
};
}
#endif // LINKLIST_H
main.cpp
#include <iostream>
#include"LinkList.h"
using namespace std;
using namespace DTLib;
int main()
{
LinkList<int> list;
for(int i=0;i<5;i++)
{
list.insert(i);
}
for(list.move(0);!list.end();list.next())
{
cout<<list.current()<<endl;
}
return 0;
}
程序崩溃!!!
问题出在哪里?
- SmartPointer的设计方案
指针生命周期结束时主动释放堆空间
—片堆空间最多只能由一个指针标识
杜绝指针运算和指针比较新的设计方案
是时候创建新的智能指针了!
新的设计方案
- Pointer是智能指针的抽象父类(模板)
纯虚析构函数virtual ~Pointer() = 0;
重载operator - > ()
重载operator * ()
2、编程实验
智能指针的新方案 Pointer.h SmartPointer.h
Pointer.h
- #ifndef POINTER_H
- #define POINTER_H
- #include"Object.h"
- namespace DTLib
- {
- 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 DTLib
- {
- 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& 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 DTLib;
- 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;
- }
To be continued ...
思考:
如何实现SharedPointer使得多个智能指针对象可
以指向同—片堆内存,同时支持堆内存的自动释放?