MFC提供了一个类似于C++ vector的ATL模版,可以实现类似于vector的功能,主要方法有如下:
void RemoveAll();
// Accessing elements
void* GetAt(INT_PTR nIndex) const;
void SetAt(INT_PTR nIndex, void* newElement);
const void** GetData() const;
void** GetData();
INT_PTR Add(void* newElement);
void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1);
void InsertAt(INT_PTR nStartIndex, CPtrArray* pNewArray);
也就是基本上的添加单个元素,插入和删除指定序列存储的元素,获得指定序号的元素,删除全部元素。
一般常用的添加元素的方式为:
CPtrArray m_testarr;
infodata m_infodata;
infodata* pindata = new infodata;
m_testarr.Add((infodata*)pindata);
即通过 new一个元素对象,然后通过add方法插入的CPtrArray的队列中;
那么当使用完后删除,相信很多人的第一想法就是通过调用RemoveAll()方法。
我们看removeall的实现:(为了方便,只截取了核心部分)
if (nNewSize == 0)
{
// shrink to nothing
if (m_pData != NULL)
{
for( int i = 0; i < m_nSize; i++ )
(m_pData + i)->~TYPE();
delete[] (BYTE*)m_pData;
m_pData = NULL;
}
m_nSize = m_nMaxSize = 0;
}
也就是说removeall里面会进行delete操作,那么事实是这样吗?
我们调试看看:
上述
infodata* pindata = new infodata;
m_testarr.Add((infodata*)pindata);
调试产生的结果如下:
执行removeall操作:
pindata = (infodata*)m_testarr.GetAt(0);
m_testarr.RemoveAll();
我们可以发现,CPtrArray的m_pdata内容为空了,但是元素指针pindata的地址却没有为0。
所以实际上removeall方法并没有释放我们之前new分配的元素。
这是因为CPtrArray的m_pdata其实是一个二级指针,他存储每个元素的地址,removeall只是释放了m_pdata。
所以需要在removeall之前通过delete释放相应元素