源自:
小银
stack是一种先进后出(First in last out)的数据结构,queue是一种先进先出(first in first out)的数据结构,在stl中实现方法是用了把deque双向队列封装了一下(具体可以查看<<stl源妈解析>>大概是第4章).
今天剥离MFC中CWinThread的类时,发现是一个MFC存放线程信息的一个队列类CSimpleList,是个队列的类和以前看到的方法都不一样它用了位移来得到p->next(比较牛啊).具体代码从MFC中剥离了出来,根据这种想法又写了stack和queue的两个类,其实是想写list的嫌麻烦,就改简单的了.重在思想.
先给出 CSimpleList代码
Simplelist.h
#ifndef __JONES__CSIMPLELIST__
#define __JONES__CSIMPLELIST__
![](/Images/OutliningIndicators/None.gif)
class CSimpleList
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
CSimpleList(int nNextOffset = 0);
void Construct(int nNextOffset);
![](/Images/OutliningIndicators/InBlock.gif)
//操作
BOOL IsEmpty() const;
void AddHead(void* p);
void RemoveAll();
void* GetHead() const;
void* GetNext(void* p) const;
BOOL Remove(void* p);
void** GetNextPtr(void* p) const;
![](/Images/OutliningIndicators/InBlock.gif)
private:
void* m_pHead;
size_t m_nNextOffset; //pNext的位移偏量
![](/Images/OutliningIndicators/InBlock.gif)
};
![](/Images/OutliningIndicators/None.gif)
//对CSimpleList的一个封装
template<class TYPE>
class CTypedSimpleList : public CSimpleList
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
CTypedSimpleList(int nNextOffset = 0)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
: CSimpleList(nNextOffset)
{ }
void AddHead(TYPE p)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ CSimpleList::AddHead(p); }
TYPE GetHead()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ return (TYPE)CSimpleList::GetHead(); }
TYPE GetNext(TYPE p)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ return (TYPE)CSimpleList::GetNext(p); }
BOOL Remove(TYPE p)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ return CSimpleList::Remove((TYPE)p); }
operator TYPE()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ return (TYPE)CSimpleList::GetHead(); }
};
![](/Images/OutliningIndicators/None.gif)
#endif
![](/Images/OutliningIndicators/None.gif)
#include "stdafx.h"
#include "SimpleList.h"
![](/Images/OutliningIndicators/None.gif)
CSimpleList::CSimpleList(int nNextOffset)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
m_pHead = NULL;
m_nNextOffset = nNextOffset;
}
![](/Images/OutliningIndicators/None.gif)
void CSimpleList::Construct(int nNextOffset)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
assert(m_pHead == NULL);
m_nNextOffset = nNextOffset;
}
![](/Images/OutliningIndicators/None.gif)
BOOL CSimpleList::IsEmpty() const
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return m_pHead == NULL;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
void** CSimpleList::GetNextPtr(void* p) const
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
assert(p != NULL);
return (void**)((BYTE*)p+m_nNextOffset);
//重点啊 配合下面的g_list.Construct(offsetof(CThreadData, pNext)); 一起看,然后画个图 是不是得到是pNext的位置
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
void CSimpleList::RemoveAll()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
m_pHead = NULL;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
void* CSimpleList::GetHead() const
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return m_pHead;
}
![](/Images/OutliningIndicators/None.gif)
void* CSimpleList::GetNext(void* prevElement) const
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return *GetNextPtr(prevElement);
}
![](/Images/OutliningIndicators/None.gif)
void CSimpleList::AddHead(void* p)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
assert(p != NULL);
assert(*GetNextPtr(p) == NULL);
![](/Images/OutliningIndicators/InBlock.gif)
*GetNextPtr(p) = m_pHead;
m_pHead = p;
}
![](/Images/OutliningIndicators/None.gif)
BOOL CSimpleList::Remove(void* p)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
assert(p != NULL);
![](/Images/OutliningIndicators/InBlock.gif)
if (m_pHead == NULL)
return FALSE;
![](/Images/OutliningIndicators/InBlock.gif)
BOOL bResult = FALSE;
if (m_pHead == p)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
m_pHead = *GetNextPtr(p);
bResult = TRUE;
}
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
void* pTest = m_pHead;
while (pTest != NULL && *GetNextPtr(pTest) != p)
pTest = *GetNextPtr(pTest);
if (pTest != NULL)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
*GetNextPtr(pTest) = *GetNextPtr(p);
bResult = TRUE;
}
}
return bResult;
}
![](/Images/OutliningIndicators/None.gif)
//调用了
![](/Images/OutliningIndicators/None.gif)
struct CThreadData
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CThreadData* pNext;
int nCount;
LPVOID* pData;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
CTypedSimpleList<CThreadData*> g_list;
int main(int argc, char* argv[])
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
g_list.Construct(offsetof(CThreadData, pNext)); //得到pNext的和CThreadData的偏量
CThreadData* pData=NULL,
pData = new CThreadData;
pData->nCount = 0;
pData->pData = NULL;
pData->pNext=NULL;
g_list.AddHead(pData);
![](/Images/OutliningIndicators/InBlock.gif)
pData = new CThreadData;
pData->nCount = 1;
pData->pData = NULL;
pData->pNext=NULL;
g_list.AddHead(pData);
![](/Images/OutliningIndicators/InBlock.gif)
pData = new CThreadData;
pData->nCount = 2;
pData->pData = NULL;
pData->pNext=NULL;
g_list.AddHead(pData);
![](/Images/OutliningIndicators/InBlock.gif)
pData=g_list;
while(pData=g_list.GetNext(pData))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
printf("%d\r\n",pData->nCount);
}
![](/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
.delete掉new出来的东西(略) 可以调Remove() 然后delete
}
//下面是我自己根据这个原理写的stock和queue 最后用模版封装了一下
#ifndef __JONES_QUEUE__STOCK
#define __JONES_QUEUE__STOCK
![](/Images/OutliningIndicators/None.gif)
class ListBase //list基类
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
void Construct(int nNextOffset); //pNext的位移
![](/Images/OutliningIndicators/InBlock.gif)
protected:
void** GetNextPtr(void* p) const; //利用位移得到pNext地址
size_t m_nNextOffset; //偏移量
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//********************************************************************/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//******************QueueList 先进先出********************************/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//********************************************************************/
class QueueList : public ListBase
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
QueueList(int nNextOffset=0);
![](/Images/OutliningIndicators/InBlock.gif)
//操作
bool empty() const;
void* front() const; //得到栈的第一个数据
void pop(); //出栈
void push(void* p); //压栈
private:
void* m_pHead; //头
void* m_pTail; //尾
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//********************************************************************/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//******************StockList 先进后出********************************/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//********************************************************************/
class StockList : public ListBase
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
StockList(int nNextOffset=0);
void pop(); //出栈
void push(void* p); //压栈
void* front() const; //得到栈的第一个数据
private:
void* m_pHead; //头
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//********************************************************************/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*封装了一下 好看点而已(起码也用到模版了,现在流行的技术,呵呵
..) */
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//********************************************************************/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
template <typename TYPE,typename LISTTYPE=QueueList /**//*list类型*/>
class SpecialList : public LISTTYPE
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
SpecialList(int nNextOffset=0)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
: LISTTYPE(nNextOffset)
{}
![](/Images/OutliningIndicators/InBlock.gif)
TYPE front()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ return (TYPE)LISTTYPE::front(); }
![](/Images/OutliningIndicators/InBlock.gif)
void push(TYPE p)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ LISTTYPE::push(p); }
![](/Images/OutliningIndicators/InBlock.gif)
};
#endif
![](/Images/OutliningIndicators/None.gif)
//调用的例子
struct CThreadData
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CThreadData* pNext;
int nCount;
LPVOID* pData;
};
![](/Images/OutliningIndicators/None.gif)
SpecialList<CThreadData*,QueueList> g_Queue;
![](/Images/OutliningIndicators/None.gif)
int main(int argc, char* argv[])
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
g_Queue.Construct(offsetof(CThreadData, pNext));
CThreadData* pData=NULL,*pTemp=NULL;
pData = new CThreadData;
pData->nCount = 0;
pData->pData = NULL;
pData->pNext=NULL;
g_Queue.push(pData);
![](/Images/OutliningIndicators/InBlock.gif)
pData = new CThreadData;
pData->nCount = 1;
pData->pData = NULL;
pData->pNext=NULL;
g_Queue.push(pData);
![](/Images/OutliningIndicators/InBlock.gif)
pData = new CThreadData;
pData->nCount = 2;
pData->pData = NULL;
pData->pNext=NULL;
g_Queue.push(pData);
![](/Images/OutliningIndicators/InBlock.gif)
while(pData=g_Queue.front())
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
printf("%d\r\n",pData->nCount);
g_Queue.pop();
delete pData;
}
return 0;
}
![](/Images/OutliningIndicators/None.gif)
最后忘了说还有1点就是 如果你用的是继承的数据
class CNoTrackObject
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual ~CNoTrackObject()
{};
![](/Images/OutliningIndicators/InBlock.gif)
};
![](/Images/OutliningIndicators/None.gif)
struct CThreadData : public CNoTrackObject
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CThreadData* pNext;
int nCount;
LPVOID* pData; )
};
那pNext位移的偏量就不是0了是4,具体可以查看<<c++对象模型>>