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

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

4

7 回答 7

111

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,mapped_type 应为 DefaultConstructible。

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

  4. 复杂性:对数。

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

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

  2. 要求:mapped_type 应为 DefaultConstructible。

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

  4. 复杂性:对数。

于 2012-04-12T13:34:38.077 回答
28

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

  1. 地图包含这个key。所以它会返回对应的key value.
  2. 该地图不包含key. 在这种情况下,它会自动key在地图中添加null value.

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

这里地图大小将增加1.

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

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

于 2014-12-20T13:18:09.797 回答
9

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

于 2012-04-12T13:35:29.650 回答
7

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

于 2012-04-12T13:35:12.707 回答
3

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

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

iterator find ( const key_type& x )

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

size_type count ( const key_type& x ) const

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

于 2012-04-12T13:44:16.570 回答
1

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

但是你应该注意,如果你访问 anot 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]调用 map 构造{5, MapValue(0)}插入到 idName。

但是,如果你调用成员函数 by 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;
于 2018-11-15T12:45:22.447 回答
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

于 2013-08-16T13:55:11.260 回答