30
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 将变得无效?

4

4 回答 4

59

第 23.1.2#8 节(关联容器要求):

插入成员不应影响迭代器和对容器的引用的有效性,而擦除成员应仅使迭代器和对被擦除元素的引用无效。

因此,是的,除非您删除元素,否则可以保证存储指向映射元素的数据成员的指针是有效的。

于 2009-02-05T14:24:56.633 回答
22

第一,地图保证稳定;即迭代器不会因元素插入或删除而失效(当然,被删除的元素除外)。

但是,迭代器的稳定性并不能保证指针的稳定性!尽管大多数实现通常会使用指针(至少在某种程度上)来实现迭代器(这意味着假设您的解决方案可以工作是非常安全的),但您真正应该存储的是迭代器本身

您可以做的是创建一个小对象,例如:

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;
}

然后存储它而不是字符串指针。

于 2009-02-05T14:12:01.167 回答
1

如果您不确定哪些操作会使您的迭代器无效,您可以在参考资料中轻松查找。例如对于vector::insert它说:

这有效地增加了向量大小,当且仅当新向量大小超过当前向量容量时,才会自动重新分配分配的存储空间。矢量容器中的重新分配使所有先前获得的迭代器、引用和指针无效。

另一方面,map::insert没有提及任何此类内容。

正如皮埃尔所说,您应该存储迭代器而不是指针。

于 2009-02-05T14:25:14.683 回答
0

你为什么要这样做?

您不能更改 *p 的值,因为它是 const std::string。如果您确实更改了它,那么您可能会通过更改元素的排序顺序来破坏容器的不变量。

除非您有其他未在此处给出的要求,否则您应该只获取字符串的副本。

于 2009-02-06T14:29:02.053 回答