使用C ++标准库的std :: map类,并注意到如果我擦除一个元素,然后尝试引用它(下面代码中注释掉的行),该元素将返回值为0。这是预期的吗?你真的必须使用find函数来访问一个元素而不会意外地创建一个元素吗?
编译器设置:我正在使用g ++编译osx 10.8.3 i686-apple-darwin11-llvm-g ++ - 4.2(GCC)4.2.1(基于Apple Inc. build 5658)(LLVM build 2336.11.00)
using namespace std;
map<int,int> myMap;
map<int,int>::iterator it;
myMap[1] = 5;
for (it=myMap.begin(); it!=myMap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
printf("map test result: %d\n", myMap[1]);
it = myMap.find(1);
myMap.erase( it );
// If I uncomment this it will cause a 0 value to occur at key 1.
//printf("map test result: %d\n", myMap[1]);
if (myMap.find(1) == myMap.end())
puts("element key 1 is null, ok");
else
puts("element @ key 1 exists, error");
if (myMap.empty())
puts("map is empty");
else
puts("map is not empty, error");
for (it=myMap.begin(); it!=myMap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
只是为了澄清一下,如果我在第二个printf行评论时运行它,它会按预期运行:
1 => 5
map test result: 5
element key 1 is null, ok
map is empty
如果我使用未注释的行运行,则在printf语句中访问myMap [1]会创建另一个元素,并保留此结果:
1 => 5
map test result: 5
map test result: 0
element @ key 1 exists, error
map is not empty, error
1 => 0
答案 0 :(得分:5)
是的,这是operator[]
std::map
应该做的事情。从标准(C ++ 11,§23.5.4.3):
mapped_type& operator[](const key_type& k); mapped_type& operator[](key_type&& k);
[...]
效果:如果unordered_map尚未包含其键等效于k的元素,则第一个运算符将插入值
value_type(k, mapped_type())
,第二个运算符将插入值value_type(std::move(k), mapped_type())
。
请注意,即使元素从未插入然后被删除,也会发生这种情况。使用operator[]
进行元素访问只需在将其应用于不存在的键时插入新的默认构造值。
如果您不想这样做,请最好使用find
的{{1}}功能。如果密钥不存在,那将返回std::map
- 迭代器。
答案 1 :(得分:2)
是的,这是预期的行为。除了阅读规范之外,您还可以从类型签名中推断出这一点:
T& operator[] (const key_type& k);
在operator =
运算符已经完成执行后,它无法判断您是否最终分配给键,因为[]
在其返回值上被调用。该方法也无法表示空值:它返回引用,而不是指针。