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;
}
總結:
人無完人,天道酬勤!