У меня похожий вопрос Вот но контекст этого нового вопроса другой.
У меня есть эта переменная: 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
) для каждой записи списка, чтобы я мог получить к ней доступ позже?
Я понимаю, что могу взять текст записи списка, а затем найти его на карте и получить таким образом. Но есть ли более прямой способ связать их вместе?
std::map
указан как ассоциативный контейнер, который никогда не перемещает существующие элементы, см. [Associative.reqmts] / 9:
insert
а такжеemplace
члены не должны влиять на действительность итераторов и ссылок на контейнер, аerase
члены должны делать недействительными только итераторы и ссылки на стертые элементы.
На практике это часто реализуется как красно-черное дерево.
Таким образом, безопасно сохранять указатели на существующие элементы, если их время жизни превышает время жизни указателей.
Обратите внимание, что вы потеряете эту гарантию, если вы переключитесь на std::unordered_map
(хеш-карта).
Установить:
m_lbPublishers.SetItemDataPtr(i, &mapPublisher.second);
Чтобы получить:
auto psEntry = (S_DEMO_ENTRY_EX*)m_lbPublishers.GetItemDataPtr(i);
CListBox::GetItemDataPtr()
возвращается void*
поэтому актерский состав обязателен.
Пока узел карты не разрушен / удален, вы можете передать указатель на сопоставленный тип данных непосредственно в CListBox::SetItemDataPtr
,
Так что в вашем случае доступ к S_DEMO_ENTRY_EX
и используя указатель, используя &mapPublisher.second
все в порядке.
Это гарантировано правилами для STL