RAII的C++漂亮的回收机制:
https://www.jianshu.com/p/3edd59f05174
迭代器设计模式:
https://blog.csdn.net/CoderAldrich/article/details/83183521
参考上述链接字节修改的代码,在VS2017实现:
/*
@Author:Leonard.Tang
@DateTime:2020/10/14
*/
#include <iostream>
using namespace std;
/*
RAII机制:
如果程序很复杂的时候,需要为所有的new 分配的内存delete掉,
导致极度臃肿,效率下降,更可怕的是,程序的可理解性和可维护性明显降低了,
当操作增多时,处理资源释放的代码就会越来越多,越来越乱。如果某一个操作
发生了异常而导致释放资源的语句没有被调用,怎么办?这个时候,
RAII机制就可以派上用场了。
*/
typedef struct NodeTag
{
int value;
struct NodeTag* pNext;
}NODE;
class JList;
class Iterator
{
public:
Iterator() {}
virtual ~Iterator() {}
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsDone() const = 0;
virtual NODE *CurrentItem() const = 0;
};
class JListIterator : public Iterator
{
public:
JListIterator(JList *pList) : m_pJTList(pList), m_pCurrent(NULL) {}
virtual ~JListIterator() {}
virtual void First();
virtual void Next();
virtual bool IsDone() const;
virtual NODE* CurrentItem() const;
private:
JList *m_pJTList;
NODE *m_pCurrent;
};
class AbstractJTList
{
public:
virtual Iterator *GetIterator() const = 0;
};
class JList: public AbstractJTList
{
public:
JList():m_pHead(NULL),m_pTail(NULL) {}
virtual ~JList();
JList(const JList &);
JList& operator=(const JList&);
long GetCount() const;
NODE *Get(const long index) const;
NODE *First() const;
NODE *Last() const;
bool Includes(const int &) const;
void Append(const int &);
void Remove(NODE *pNode);
void RemoveAll();
//返回一个一个固定的指针,避免客户端创建 指针
virtual Iterator *GetIterator() const
{
return new JListIterator(const_cast<JList*>(this)); //这里需要 const_cast<JList*>(x)强制转换成const JList *
}
private:
NODE *m_pHead;
NODE *m_pTail;
long m_lCount;
};
//这里为什么要这么做的原因是采用了RAII回溯删除对象分配的空间的问题
//由于GetIterator返回了一个new对象,所以如果不想代码经常delete或者存在内存泄漏的可能,
//采用此机制还是很不错的
class IteratorPtr
{
public:
IteratorPtr() {}
IteratorPtr(Iterator *pIterator) : m_pIterator(pIterator) {}
~IteratorPtr() { delete m_pIterator; }
/*这里就是指针和引用的 操作描述符 对于"左值"使用的地方*/
Iterator *operator->() { return m_pIterator; }
Iterator &operator*() { return *m_pIterator; }
private:
IteratorPtr(const IteratorPtr &p) {}
IteratorPtr &operator=(const IteratorPtr &p) {}
void *operator new(size_t size) {}
void operator delete(void *p) {}
private:
Iterator *m_pIterator;
};
JList::JList(const JList& p)
{
this->m_lCount = p.m_lCount;
this->m_pHead = p.m_pHead;
this->m_pTail = p.m_pTail;
}
JList& JList::operator=(const JList &p)
{
this->m_lCount = p.m_lCount;
this->m_pHead = p.m_pHead;
this->m_pTail = p.m_pTail;
return *this;
}
JList::~JList()
{
NODE *pCurrent = m_pHead;
NODE *pNextNode = NULL;
while (pCurrent)
{
pNextNode = pCurrent->pNext;
delete pCurrent;
pCurrent = pNextNode;
}
}
long JList::GetCount() const
{
return m_lCount;
}
NODE* JList::Get(const long index) const
{
// The min index is 0, max index is count - 1
if (index > m_lCount - 1 || index < 0)
{
return NULL;
}
int iPosTemp = 0;
NODE *pNodeTemp = m_pHead;
while (pNodeTemp)
{
if (index == iPosTemp++)
{
return pNodeTemp;
}
pNodeTemp = pNodeTemp->pNext;
}
return NULL;
}
NODE* JList::First() const
{
return m_pHead;
}
NODE* JList::Last() const
{
return m_pTail;
}
bool JList::Includes(const int &value) const
{
NODE *pNodeTemp = m_pHead;
while (pNodeTemp)
{
if (value == pNodeTemp->value)
{
return true;
}
pNodeTemp = pNodeTemp->pNext;
}
return false;
}
void JList::Append(const int &value)
{
// Create the new node
NODE *pInsertNode = new NODE;
pInsertNode->value = value;
pInsertNode->pNext = NULL;
// This list is empty
if (m_pHead == NULL)
{
m_pHead = m_pTail = pInsertNode;
}
else
{
m_pTail->pNext = pInsertNode;
m_pTail = pInsertNode;
}
++m_lCount;
}
void JList::Remove(NODE *pNode)
{
if (pNode == NULL || m_pHead == NULL || m_pTail == NULL)
{
return;
}
if (pNode == m_pHead) // If the deleting node is head node
{
NODE *pNewHead = m_pHead->pNext;
m_pHead = pNewHead;
}
else
{
// To get the deleting node's previous node
NODE *pPreviousNode = NULL;
NODE *pCurrentNode = m_pHead;
while (pCurrentNode)
{
pPreviousNode = pCurrentNode;
pCurrentNode = pCurrentNode->pNext;
if (pCurrentNode == pNode)
{
break;
}
}
// To get the deleting node's next node
NODE *pNextNode = pNode->pNext;
// If pNextNode is NULL, it means the deleting node is the tail node, we should change the m_pTail pointer
if (pNextNode == NULL)
{
m_pTail = pPreviousNode;
}
// Relink the list
pPreviousNode->pNext = pNextNode;
}
// Delete the node
delete pNode;
pNode = NULL;
--m_lCount;
}
void JList::RemoveAll()
{
delete this;
}
void JListIterator::First()
{
m_pCurrent = m_pJTList->First();
}
void JListIterator::Next()
{
m_pCurrent = m_pCurrent->pNext;
}
bool JListIterator::IsDone() const
{
return m_pCurrent == m_pJTList->Last()->pNext;
}
NODE* JListIterator::CurrentItem() const
{
return m_pCurrent;
}
int main(int argc,const char* argv[])
{
JList *pJTList = new JList();
pJTList->Append(10);
pJTList->Append(20);
pJTList->Append(30);
pJTList->Append(40);
pJTList->Append(50);
pJTList->Append(60);
pJTList->Append(70);
pJTList->Append(80);
pJTList->Append(90);
pJTList->Append(100);
//Iterator *pIterator = new JListIterator(pJTList);
IteratorPtr pIterator(pJTList->GetIterator()); //这里就是RAII回收机制
// Print the list by JTListIterator
for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
{
cout << pIterator->CurrentItem()->value << "->";
}
cout << "END" << endl;
// Test for removing
NODE *pDeleteNode = NULL;
for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
{
pDeleteNode = pIterator->CurrentItem();
if (pDeleteNode->value == 100)
{
pJTList->Remove(pDeleteNode);
break;
}
}
// Print the list by JTListIterator
for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
{
cout << pIterator->CurrentItem()->value << "->";
}
cout << "END" << endl;
// delete pIterator;
delete pJTList;
getchar();
return 0;
}
总结:
人无完人,天道酬勤!