如果我在键不存在的情况下读取地图的值,会发生什么情况?
What happens if I read a map's value where the key does not exist?
map<string, string> dada;
dada["dummy"] = "papy";
cout << dada["pootoo"];
我很困惑,因为我不知道它是否被认为是未定义的行为,当我请求不存在的键时,我是否只使用 find 代替?
map::operator[]
在数据结构中搜索与给定键对应的值,并返回对该键的引用。
如果找不到,它会透明地为其创建一个默认构造元素。 (如果您不希望此行为,可以改用 map::at
函数。
您可以在此处获取 std::map 方法的完整列表:
http://en.cppreference.com/w/cpp/container/map
以下是当前C++标准中map::operator[]
的文档...
23.4.4.3 映射元素访问
T& operator[](const key_type& x);
效果:如果映射中没有等效于 x 的键,则在映射中插入 value_type(x, T())。
要求:key_type应为可复制可构造的,mapped_type应为默认可构造的。
返回:对 *this 中 x 对应的mapped_type的引用。
复杂度:对数。
T& operator[](key_type&& x);
效果:如果映射中没有等效于 x 的键,则在映射中插入 value_type(std::move(x), T())。
要求:mapped_type应为默认可构造的。
返回:对 *this 中 x 对应的mapped_type的引用。
复杂度:对数。
如果您尝试使用索引运算符 []
访问key value
,则可能会发生 2 种情况:
- 地图包含此
key
。所以它将返回相应的key value
。 - 地图不包含
key
。在这种情况下,它会自动向地图添加带有null value
key
。
"pootoo"
键在您的地图中不存在。因此,它将自动添加带有value = ""
(空字符串)的此key
。您的程序将打印空字符串。
这里的地图大小将增加1
。
要搜索密钥,可以使用 map_name.find()
,如果密钥不存在,它将返回map_name.end()
。并且不会添加额外的key
。
设置键的值,可以使用运算符[]
。
这不是未定义的行为。如果operator []
找不到所提供键的值,则会在该位置插入一个值。
对于 operator[],如果您尝试访问不存在的键的值,则将默认构造的新值对象放入映射中并返回其引用。
map
的operator[]
返回一个非常量引用,您可以按照第二行显示的方式使用它进行分配。以这种方式访问将创建value
类型的默认构造元素。
如果你想找到一个元素,更好的方法是
iterator find ( const key_type& x )
(或 const 替代方案),如果找不到键,或者您只是想知道它是否在集合中,它将返回一个等于 <map>.end()
的迭代器
size_type count ( const key_type& x ) const
对于映射,它将始终返回 1 或 0,因为键是唯一的。
如果运算符 [] 找不到所提供键的值,则会在该位置插入一个值。
但是你应该注意,如果你访问一个not exist key
并调用它的成员函数,比如mapKV[not_exist_key].member_fun()。程序可能会崩溃。
我举个例子,测试类如下:
struct MapValue{
int val;
MapValue(int i=0){
cout<<"ctor: "<<i<<endl; val = i;
}
~MapValue(){
cout<<"dtor: "<<val<<endl;
}
friend ostream& operator<<(std::ostream& out, const MapValue& mv){
cout<<"MapValue: "<<mv.val<<endl;
}
string toString(){
cout<<"MapValue: "<<val<<endl;
}
};
测试代码:
cout<<"-------create map<int, MapValue>-------"<<endl;
map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};
cout<<"-----cout key[2]-----"<<endl;
cout<<idName[2]<<endl;
cout<<"-----cout key[5]-----"<<endl;
cout<<idName[5]<<endl;
cout<<"------- runs here means, does't crash-------"<<endl;
输出如下:
-------create map<int, MapValue>-------
ctor: 1
ctor: 2
dtor: 2
dtor: 1
dtor: 2
dtor: 1
-----cout key[2]-----
MapValue: 2
-----cout key[5]-----
ctor: 0
MapValue: 0
-------runs here means, does't crash-------
dtor: 0
dtor: 2
dtor: 1
我们可以看到:idName[5]
调用地图构造{5, MapValue(0)}
插入到 idName。
但是,如果您通过 idName[5]
调用成员函数,则程序崩溃:
cout<<"-------create map<int, MapValue>-------"<<endl;
map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};
idName[5].toString(); // get crash here.
cout<<"------- runs here means, doesn't crash-------"<<endl;
请查看out_of_range例外:http://www.cplusplus.com/reference/stdexcept/out_of_range/
这就是 map::at 和 map::operator[] 在键不存在时将抛出的内容。您可以像链接中的矢量示例一样捕获它。
您还可以使用:http://www.cplusplus.com/reference/map/map/find/
并对照地图::结束
- 将指针分配给另一个指针时会发生什么情况?
- 在什么情况下,两个堆栈分配的结构对象的 this 点指向同一个地址?
- 在什么情况下,我想在 C/C++ 代码中使用内联汇编代码
- 发生注入类名时会发生什么情况?(C++)
- 在什么情况下,需要共享智能指针而无法使用唯一指针?
- 重新分配向量时,向量中的内存会发生什么情况
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- 为什么或在什么情况下,你会将参数作为C++中的引用(或指针)传递给函数?
- 如果我向一个12字节的缓冲区写入的字节数少于12,会发生什么情况
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 如果我在 c++ 中以 new 的放置形式使用没有足够的内存,会发生什么情况?
- 使用 Google 基准测试时返回值会发生什么情况?
- 正在连接的等待条件变量的线程会发生什么情况?
- 如果未定义的C++行为符合 C 定义的行为,会发生什么情况?
- 在什么情况下,使用'const T*'输入参数比'const T&'更可取?
- 如果字符串在 C/C++ 中没有 NUL 字符(以防编译器允许它通过)会发生什么情况?
- 将虚拟方法定义为私有方法时会发生什么情况?
- 如果我将"reference to vector"分配给"vector"会发生什么情况
- 在什么情况下,从流(结束)读取会导致停止?
- 如果我在键不存在的情况下读取地图的值,会发生什么情况?