如果我读取不存在密钥的地图值,会发生什么?

时间:2012-04-12 13:33:32

标签: c++ map

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

我很困惑,因为我不知道它是否被认为是未定义的行为,如何知道我何时请求不存在的密钥,我只是使用find吗?

7 个答案:

答案 0 :(得分:59)

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

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

  2. 要求:key_type应为CopyConstructible,mapped_type应为DefaultConstructible。

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

  4. 复杂性:对数。

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

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

    2. 要求:mapped_type应为DefaultConstructible。

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

    4. 复杂性:对数。

答案 1 :(得分:14)

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

  1. 地图包含此key。因此它将返回相应的key value
  2. 地图不包含key。在这种情况下,它会自动使用key向地图添加null value
  3. "pootoo"密钥不存在于您的地图中。因此,它会自动添加key value = ""(空字符串)。并且您的程序将打印空字符串。

    此处地图尺寸将增加1

    要搜索密钥,您可以使用map_name.find(),如果密钥不存在,将返回map_name.end()。并且不会添加额外的key

    如果要为密钥设置值,可以使用[]运算符。

答案 2 :(得分:7)

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

答案 3 :(得分:6)

对于operator [],如果您尝试访问不存在的键的值,则默认构造的新值对象将被放入地图并返回它的引用。

答案 4 :(得分:2)

operator[] map会返回非const引用,您可以按照第二行显示的方式使用该引用进行分配。以这种方式访问​​将创建value类型的默认构造元素。

如果你想找到一个元素,一个更好的方法是

iterator find ( const key_type& x )

(或const替代)如果找不到密钥将返回等于<map>.end()的迭代器,或者如果你只是想知道它是否在集合中你可以使用

size_type count ( const key_type& x ) const

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

答案 5 :(得分: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]调用映射结构{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, does't crash-------"<<endl;

答案 6 :(得分:0)

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

如果key不存在,这就是map :: at和map :: operator []将抛出的内容。您可以像链接中的矢量示例一样捕获它。

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

并检查map :: end