将std :: map项设置为CListBox的itemdata

时间:2018-03-28 08:05:06

标签: c++ mfc stdmap clistbox

我有一个类似的问题here,但这个新问题的背景不同。

背景

我有这个变量:PublisherMap m_mapPublishers;

PublisherMap的定义是:

using PublisherMap = std::map<CString, S_DEMO_ENTRY_EX>;

代码

我有这种方法可以读取地图并填充CListBox

bool CChristianLifeMinistryPersonalCopiesDlg::InitPublishersGrid()
{
    try
    {
        m_lbPublishers.ResetContent();

        for (auto & mapPublisher : m_mapPublishers)
        {
            bool bInclude = false;

            if (m_iDisplayMode == DISPLAY_EVERYONE)
                bInclude = true;
            else if (m_iDisplayMode == DISPLAY_BROTHER && mapPublisher.second.eGender == GENDER_MALE)
                bInclude = true;
            else if (m_iDisplayMode == DISPLAY_SISTER && mapPublisher.second.eGender == GENDER_FEMALE)
                bInclude = true;

            if (bInclude && m_bLimitDisplay)
            {
                CString strTemp;
                if (!m_mapSSAssignedPublishers.Lookup(mapPublisher.first, strTemp))
                    bInclude = FALSE;
            }

            if (bInclude)
            {
                int i = m_lbPublishers.AddString(mapPublisher.first);
                m_lbPublishers.SetItemData(i, MAKEWPARAM(mapPublisher.second.eGender, mapPublisher.second.eAppointed));

            }
        }
    }
    catch (_com_error e)
    {
        LPCTSTR szError = e.ErrorMessage();
        AfxMessageBox(szError);
        return false;
    }
    catch (CException* e)
    {
        e->Delete();
        AfxMessageBox(_T("CException"));
        return false;
    }

    m_iSelectMode = SELECT_NONE;
    UpdateData(FALSE);

    return true;
}

请注意,我使用的是商品数据:

m_lbPublishers.SetItemData(i, 
    MAKEWPARAM(mapPublisher.second.eGender, mapPublisher.second.eAppointed));

它绝对正常。如果我使用CPtrArray,我会为列表框中的每个条目分配实际的结构对象指针。

问题

我不完全了解std::map的机制。是否有任何安全的方法可以直接将地图中的每个条目(mapPublisher)与每个列表框条目相关联,以便以后可以访问它?

我意识到我可以获取列表框条目的文本,然后在地图中找到它并以此方式获取。但是,如果有更直接的方法将两者联系在一起吗?

2 个答案:

答案 0 :(得分:4)

std::map被指定为永远不会移动现有元素的关联容器,请参阅[associative.reqmts]/9

  

insertemplace成员不应影响迭代器和对容器的引用的有效性,erase成员应仅使迭代器和对已擦除元素的引用无效。

在实践中,它通常被实现为红黑树。

因此,保持指向现有元素的指针是安全的,只要它们的生命周期超过指针的生命周期。

请注意,如果切换到std::unordered_map(哈希映射),您将失去该保证。

设置:

    m_lbPublishers.SetItemDataPtr(i, &mapPublisher.second);

要检索:

    auto psEntry = (S_DEMO_ENTRY_EX*)m_lbPublishers.GetItemDataPtr(i);

CListBox::GetItemDataPtr()会返回void*,因此需要进行投射。

答案 1 :(得分:2)

只要不破坏/删除映射的节点,就可以将指向映射的数据类型的指针直接传递给CListBox::SetItemDataPtr

因此,在您的情况下访问S_DEMO_ENTRY_EX并使用&mapPublisher.second指针是正常的。

这由STL的规则保证