天天看點

C++ 疊代器+RAII機制簡易實作總結:

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;
}

           

總結:

人無完人,天道酬勤!

繼續閱讀