天天看点

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

           

总结:

人无完人,天道酬勤!

继续阅读