C++ 如果我在键不存在的情况下读取地图的值会发生什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10124679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:39:07  来源:igfitidea点击:

What happens if I read a map's value where the key does not exist?

c++map

提问by jokoon

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

I'm puzzled because I don't know if it's considered undefined behaviour or not, how to know when I request a key which does not exist, do I just use find instead ?

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

回答by Andrew Tomazos

The map::operator[]searches the data structure for a value corresponding to the given key, and returns a reference to it.

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

If it can't find one it transparently creates a default constructed element for it. (If you do not want this behaviour you can use the map::atfunction instead.)

如果它找不到一个,它会透明地为它创建一个默认的构造元素。(如果您不想要这种行为,您可以改用该map::at函数。)

You can get a full list of methods of std::map here:

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

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

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

Here is the documentation of map::operator[]from the current C++ standard...

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

23.4.4.3 Map Element Access

23.4.4.3 地图元素访问

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

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

  1. Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.

  2. Requires: key_type shall be CopyConstructible and mapped_type shall be DefaultConstructible.

  3. Returns: A reference to the mapped_type corresponding to x in *this.

  4. Complexity: logarithmic.

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

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

  3. 返回: 对与 *this 中的 x 对应的映射类型的引用。

  4. 复杂度:对数。

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

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

  1. Effects: If there is no key equivalent to x in the map, inserts value_type(std::move(x), T()) into the map.

  2. Requires: mapped_type shall be DefaultConstructible.

  3. Returns: A reference to the mapped_type corresponding to x in *this.

  4. Complexity: logarithmic.

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

  2. 要求:mapped_type 应为 DefaultConstructible。

  3. 返回: 对与 *this 中的 x 对应的映射类型的引用。

  4. 复杂度:对数。

回答by Mohammad Ali Akber

If you try to access a key valueusing index operator [], then 2 things can happen :

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

  1. The map contains this key. So it will return the corresponding key value.
  2. The map doesn't contain the key. In this case, it will automatically add a keyto the map with null value.
  1. 地图包含这个key。所以它会返回相应的key value.
  2. 地图不包含key. 在这种情况下,它会自动key向地图添加null value

"pootoo"key does't exist in your map. So it will automatically add this keywith value = ""(empty string). And your program will print empty string.

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

Here map size will increase by 1.

这里地图大小将增加1.

To search a key you can use map_name.find(), which will return map_name.end()if the key doesn't exist. And no extra keywill be added.

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

You can use []operator when you want to set value for a key.

[]当您想为键设置值时,可以使用运算符。

回答by Luchian Grigore

It's not undefined behavior. If operator []doesn't find a value for the provided key, it inserts one at that position.

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

回答by Michael Kohne

For operator[], if you try to access a value for a key that doesn't exist, a new value object that has been default constructed will be put into the map and it's reference returned.

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

回答by Component 10

The operator[]for mapreturns a non-const reference and you can assign using that in the way you've shown on your second line. Accessing in this way will create a default contructed element of valuetype.

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

If you want to find a find an element, a better way is

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

iterator find ( const key_type& x )

(or the const alternative) which will return an iterator equal to <map>.end()if it doesn't find the key, or if you just want to know if it's in the collection you can use

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

size_type count ( const key_type& x ) const

which will always return either 1 or 0 for a map since keys are unique.

由于键是唯一的,因此对于映射将始终返回 1 或 0。

回答by Jayhello

If operator [] doesn't find a value for the provided key, it inserts one at that position.

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

But you should notethat if you visit a not exist keyand invoke it's member function, like mapKV[not_exist_key].member_fun().The program may crash.

但是你应该注意,如果你访问anot exist key并调用它的成员函数,比如mapKV[not_exist_key].member_fun()。程序可能会崩溃。

Let me give an example, test class as below:

让我举个例子,测试类如下:

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

Test code:

测试代码:

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;

Output as below:

输出如下:

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

We can see that: idName[5]invoke map construct {5, MapValue(0)}to insert to idName.

我们可以看到:idName[5]调用 map 构造{5, MapValue(0)}插入到 idName。

But if, you invoke member function by idName[5], then the program crashes :

但是,如果您通过 调用成员函数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;

回答by Jayhello

please have a look at the out_of_range exception: http://www.cplusplus.com/reference/stdexcept/out_of_range/

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

this is what map::at and map::operator[] will throw if key does not exist. You can catch it the same way as the vector example in the link.

如果键不存在,这就是 map::at 和 map::operator[] 将抛出的内容。您可以按照与链接中的矢量示例相同的方式来捕获它。

You can also use: http://www.cplusplus.com/reference/map/map/find/

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

And check against map::end

并检查 map::end