Подтвердить что ты не робот

Std:: map, указатель на значение ключа карты, возможно ли это?

std::map<std::string, std::string> myMap;

std::map<std::string, std::string>::iterator i = m_myMap.find(some_key_string);
if(i == m_imagesMap.end())
    return NULL;

string *p = &i->first;

Действительна ли последняя строка? Я хочу сохранить этот указатель p в другом месте, будет ли он действительным для всей жизни программы? Но что произойдет, если я добавлю еще несколько элементов на эту карту (с другими уникальными ключами) или удалю некоторые другие ключи, не перераспределите эту строку (пару ключ-значение), так что p станет недействительным?

4b9b3361

Ответ 1

Во-первых, карты гарантированно стабильны; т.е. итераторы не являются недействительными посредством вставки или удаления элементов (за исключением того, что элемент, конечно, удаляется).

Однако стабильность итератора не гарантирует стабильности указателей! Хотя обычно бывает, что большинство реализаций используют указатели - по крайней мере на некотором уровне - для реализации итераторов (что означает, что вполне безопасно предположить, что ваше решение будет работать), то, что вы действительно должны хранить, это сам итератор.

Что вы можете сделать, так это создать небольшой объект, например:

struct StringPtrInMap
{
  typedef std::map<string,string>::iterator iterator;
  StringPtrInMap(iterator i) : it(i) {}
  const string& operator*() const { return it->first; }
  const string* operator->() const { return &it->first; }
  iterator it;
}

И затем сохраните это вместо указателя строки.

Ответ 2

Раздел 23.1.2 # 8 (требования к ассоциативным контейнерам):

Элементы вставки не должны влиять на действительность итераторов и ссылок на контейнер, а члены стирания делают недействительными только итераторы и ссылки на стертые элементы.

Таким образом, гарантируется, что сохранение указателей на элементы данных элемента карты будет действительным, если вы не удалите этот элемент.

Ответ 3

Если вы не уверены, какие операции будут аннулировать ваши итераторы, вы можете легко найти его в reference. Например, для vector:: insert говорится:

Это эффективно увеличивает размер вектора, что приводит к автоматическому перераспределению выделенного пространства памяти, если и только если новый векторный размер перекрывает текущую векторную емкость. Перераспределения в векторных контейнерах аннулируют все ранее полученные итераторы, ссылки и указатели.

map:: insert, с другой стороны, не упоминает ничего подобного.

Как сказал Пьер, вы должны сохранить итератор, а не указатель.

Ответ 4

Почему вы хотите это сделать?

Вы не можете изменить значение * p, так как оно const std::string. Если вы его изменили, вы можете разбить инварианты контейнера, изменив порядок сортировки элементов.

Если у вас нет других требований, которые вы здесь не указали, вам нужно просто взять копию строки.