CAtlList :: RemoveAt делает недействительными существующие позиции? - PullRequest
1 голос
/ 04 декабря 2009

Я смотрю на это, где m_Rows является CAtlList:

void CData::RemoveAll()
{
    size_t cItems = m_Rows.GetCount();
    POSITION Pos = m_Rows.GetHeadPosition();

    while(Pos != 0)
    {
        CItem* pItem = m_Rows.GetAt(Pos);

        if (pItem != 0)
            delete pItem;

        POSITION RemoveablePos = Pos;
        pItem = m_Rows.GetNext(Pos);

        m_Rows.RemoveAt(RemoveablePos);
    }
}

и мне интересно, есть ли вероятность, что вызов RemoveAt может сделать недействительным Pos?

1 Ответ

1 голос
/ 04 декабря 2009

Согласно документации , CAtlList ведет себя как двойной связанный список, поэтому удаление одного элемента списка должно сделать недействительными указатели на другие элементы. Тип POSITION напрямую ссылается на ячейку памяти элемента списка:

Большинство методов CAtlList используют значение позиции. Это значение используется методами для ссылки на фактическую область памяти, где хранятся элементы, и не должно рассчитываться или прогнозироваться напрямую.

Похоже, что это не так в atlcoll.h:

template< typename E, class ETraits >
void CAtlList< E, ETraits >::RemoveAt( POSITION pos )
{
ATLASSERT_VALID(this);
ATLENSURE( pos != NULL );

CNode* pOldNode = (CNode*)pos;

// remove pOldNode from list
if( pOldNode == m_pHead )
{
    m_pHead = pOldNode->m_pNext;
}
else
{
    ATLASSERT( AtlIsValidAddress( pOldNode->m_pPrev, sizeof(CNode) ));
    pOldNode->m_pPrev->m_pNext = pOldNode->m_pNext;
}
if( pOldNode == m_pTail )
{
    m_pTail = pOldNode->m_pPrev;
}
else
{
    ATLASSERT( AtlIsValidAddress( pOldNode->m_pNext, sizeof(CNode) ));
    pOldNode->m_pNext->m_pPrev = pOldNode->m_pPrev;
}
FreeNode( pOldNode );
}
...