C++地图反演初始化

C++ map inversion initialize

本文关键字:初始化 地图 C++      更新时间:2023-10-16

当我阅读一些文章时,我看到了一些奇怪的东西(对我来说)。

当我使用地图时,我是这样使用它的:

std::map<std::string, MyClass> Map;
//and add elements:
Map['someting'] = myObject;

这很好,可以理解。但是在这篇文章中,我看到了这个:

MyClass& object = Map['something_new'];
//and then, initialize the object
object.method();
//and later I can use this map
Map['something_new'];

而且......它有效。但我不明白怎么做。我初始化了一个对象引用,而不是map,但这就像我刚刚向地图中添加了一个元素一样。有人可以向我解释一下吗?

正如std::map operator[]的文档所说:

返回对映射到等效键的值的引用,如果此类键尚不存在,则执行插入

换句话说,std::map的设计是这样的,你总是通过 operator[] 获得对现有有效元素的引用,无论是在调用之前存在的元素还是动态创建的元素。

当然,其他设计也是可能的。例如,如果键不存在,则可能会引发异常,或者行为可能已未定义。但是自动元素创建是std::map最终的结果。

如果不希望自动插入元素,则不应使用 operator[] 。您可以改用以下内容:

auto const find_iter = Map.find("something_new");
if (find_iter != Map.end())
{
    MyClass& object = *find_iter;
    // ...
}
else
{
    // do whatever you want when there is no "something_new" element
    // ...
}

如果访问不存在的键,std::map将使用默认构造函数自动创建新对象。

请参阅此示例:

#include <string>
#include <iostream>
#include <map>
class Demo {
public:
    Demo() { std::cout << "ctor" << std::endl; }
};
int main(int argc, const char * argv[]) {
    std::map<std::string, Demo> m;
    std::cout << "Access unknown element." << std::endl;
    m["a"];
    m["b"];
    m["c"];
}

输出为:

访问未知元素。克托尔克托尔克托尔

访问的每个不存在的元素都是使用默认构造函数自动构造的。这也适用于简单的数据类型,如 int .

operator[](element_access)不是常量函数;如果键的值尚不存在,它实际上会在映射中插入一个新元素。

map['non_existing_key']实际上会增加容器的size()

如果k与容器中任何元素的键不匹配,则 函数使用该键插入一个新元素并返回引用 到其映射值。请注意,这总是会增加容器 大小为 1,即使没有为元素分配映射值 ( 元素是使用其默认构造函数构造的)。

第一个代码

std::map<std::string, MyClass> Map;
//and add elements:
Map["someting"] = myObject;
  1. 创建地图Map
  2. 您将下标运算符称为 Mapoperator[]。假设键"something"不存在,则通过调用默认构造函数 MyClass 来创建与此键对应的MyClass实例。
  3. 下标运算符返回对此新创建的实例的非常量引用。
  4. 赋值运算符
  5. 调用隐式或显式,复制或移动MyClass实例的赋值运算符Map,将myObject作为参数发送给它。
  6. 假设赋值操作进展顺利,myObject 被分配给键。

第二个代码

MyClass& object = Map["something_new"];
//and then, initialize the object
object.method();
//and later I can use this map
Map["something_new"];
  1. 通过调用默认构造函数 MyClass 来创建与键"something_new"对应的新 MyClass(假设它不存在)实例。
  2. 您将获得对该实例的引用。
  3. 你通过使用这个引用来完成你的工作(即调用method())。
  4. 稍后,您可以使用相同的密钥获取相同的引用。

结果

这里没有什么可比较的。第一个代码进行赋值,第二个代码调用方法。