如果我在不存在键的情况下读取地图的值会怎样?


78
map<string, string> dada;
dada["dummy"] = "papy";
cout << dada["pootoo"];

我很困惑,因为我不知道它是否被认为是未定义的行为,如何知道何时我请求一个不存在的键,我只是使用find来代替?

Answers:


84

map::operator[]对应于给定键的值的数据结构的搜索,并返回到它的基准。

如果找不到,它将透明地为其创建一个默认的构造元素。(如果您不希望出现这种情况,则可以使用该map::at函数。)

您可以在此处获得std :: map方法的完整列表:

http://en.cppreference.com/w/cpp/container/map

这是map::operator[]当前C ++标准的文档...

23.4.4.3地图元素访问

T& operator[](const key_type& x);

  1. 效果:如果在映射中没有等效于x的键,则将value_type(x,T())插入到映射中。

  2. 要求:key_type必须为CopyConstructible,而mapd_type必须为DefaultConstructible。

  3. 返回:对与* this中的x对应的mapping_type的引用。

  4. 复杂度:对数。

T& operator[](key_type&& x);

  1. 效果:如果地图中没有等效于x的键,则将value_type(std :: move(x),T())插入地图。

  2. 要求:mapped_type必须是DefaultConstructible。

  3. 返回:对与* this中的x对应的mapping_type的引用。

  4. 复杂度:对数。


我实际上没有在标准中找到任何说明它的地方。至少不是在23.3.1.2 [lib.map.access]或其他我记得要检查的地方。编辑:显然我在看该标准的旧版本。我的错。
弗拉德·希奥巴努

@VladCiobanu:以上是逐字逐句复制的23.4.4.3。您使用的是当前版本ISO/IEC 14882:2011(E)吗?
Andrew Tomazos 2012年

20

如果您尝试访问key valueusing索引运算符[],则可能会发生两种情况:

  1. 该地图包含此key。因此它将返回对应的key value
  2. 地图不包含key。在这种情况下,它将使用将自动key向地图添加null value

"pootoo"键在您的地图中不存在。因此,它会自动添加这keyvalue = ""(空字符串)。并且您的程序将打印空字符串。

这里的地图大小将增加1

要搜索关键字,您可以使用map_name.find()map_name.end()如果关键字不存在,它将返回。并且不会key添加任何额外的内容。

[]要设置键值时可以使用运算符。


7

这不是未定义的行为。如果operator []找不到所提供键的值,则在该位置插入一个。


6

对于operator [],如果尝试访问不存在的键的值,则将默认构造的新值对象放入映射中,并返回其引用。


2

operator[]map返回非const引用,你可以分配使用的方式,你已经证明你的第二行。以这种方式访问​​将创建一个默认的value类型为contructed的元素。

如果要查找元素,最好的方法是

iterator find ( const key_type& x )

(或const替代方法),它将返回等于<map>.end()没有找到键的迭代器,或者如果您只是想知道它是否在集合中,则可以使用

size_type count ( const key_type& x ) const

由于键是唯一的,因此对于地图始终返回1或0。


1

如果运算符[]找不到所提供键的值,则会在该位置插入一个。

请注意,如果您访问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]invoke map构造{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;

它不会崩溃,因为地图一定是其他错误
isti_spl,

0

请查看out_of_range异常:http ://www.cplusplus.com/reference/stdexcept/out_of_range/

如果键不存在,则map :: at和map :: operator []将抛出此错误。您可以按链接中的矢量示例一样捕获它。

您还可以使用:http : //www.cplusplus.com/reference/map/map/find/

并对照map :: end


4
不,只有key :: at抛出,map :: operator []如果密钥不存在
则会
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.