在C++中将值的引用存储在std::map中

7

我理解的是否正确:在std::map中添加/删除元素不会影响其他元素(即不会导致它们在内存中重新定位),因此以下操作是安全的:

我查看了各种包含有关容器信息的网站,但只发现了迭代器无效的情况,这已经是我知道的了...

std::map<std::string,std::string> map;
PopulateMap(map);
std::string &a= map["x"];
AddMoreData(map);
RemoveRandomKeysExceptX(map);
map["x"] = "foo";
std::cout << a << " " << map["x"] << std::endl;//prints "foo foo"
a = "bar";
std::cout << a << " " << map["x"] << std::endl;//prints "bar bar"

我在 VC9 上测试了一些类似的代码,看起来可以工作,但这并不意味着我只是运气好或者它在不同的编译器上表现不同。


不确定为什么你删除了你的回答,Nadeen,就我所看到的,它是正确的。 - CiscoIPPhone
Naveen的回答涉及到迭代器,而这个问题并不是关于迭代器的。 - anon
我也删除了我的答案,因为再读一遍,我完全不清楚实际问题是什么。 - anon
正如litb所指出的那样:https://dev59.com/53RB5IYBdhLWcg3wxZ_Y - Martin York
3个回答

9

在关于关联容器的标准中,23.1.2/8明确规定:

插入元素不应影响容器中的迭代器和引用的有效性;删除元素只应使指向已删除元素的迭代器和引用失效。


+1. 我需要随手备份一份标准。我的回答可能可以更简洁明确。 - CiscoIPPhone
是的,保持okular / acroread实例始终打开以便快速查找东西总是一个好主意 =)在这种情况下,我记得我在这里进行的讨论:https://dev59.com/53RB5IYBdhLWcg3wxZ_Y =) - Johannes Schaub - litb
我鼓励你给@greg-rogers的答案点赞。因为显然它是正确的,而被采纳的答案则说你不能确定这一点。但标准非常清楚,指针仍然保持有效。 - Johannes Schaub - litb
“看看答案”,你指的是哪一个?我没有看到任何一个来自“greg-rogers”的答案。 - Fire Lancer
我的意思是我上面链接的那个问题 :) - Johannes Schaub - litb

4

Map 具有重要属性,即向 map 中插入新元素不会使指向现有元素的迭代器失效。引用自 sgi 文档

如果迭代器保证不会改变,则它们所指向的值也不会改变。

naveen 之前给出了类似的答案。除非我的逻辑有误,你所做的是安全的。

编辑 2: 请参见 sgi 文档 中的第三点,了解从 operator[] 获取值与从迭代器获取值相同的原因。


1
正如我向Naveen(不是Nadeen)指出的那样,这个问题与迭代器无关。 - anon
我知道,但是运算符[]使用迭代器。 - CiscoIPPhone
请注意,当涉及到细节时,SGI文档有时与标准库存在小的差异。 - Johannes Schaub - litb

0

没错,你可以信赖它。

// retrieve reference to string stored at "x"
// note that since [] returns a reference, it must insert an element at "x" if 
// it doesn't exists (in this case an empty string)
std::string &a= map["x"];

// retrieve reference for "x" again and set value to "foo"
map["x"] = "foo";

// use already stored reference
a = "bar";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接