前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++(STL):30 ---关联式容器map的operator[]和insert效率对比

C++(STL):30 ---关联式容器map的operator[]和insert效率对比

作者头像
用户3479834
发布2021-02-03 14:47:01
1.3K0
发布2021-02-03 14:47:01
举报
文章被收录于专栏:游戏开发司机

通过前面的学习我们知道,map 容器模板类中提供有 operator[ ] 和 insert() 这 2 个成员方法,而值得一提的是,这 2 个方法具有相同的功能,它们既可以实现向 map 容器中添加新的键值对元素,也可以实现更新(修改)map 容器已存储键值对的值。 举个例子(程序一):

代码语言:javascript
复制
#include <map>  //map
#include <string> //string
#include <iostream>
using namespace std;

int main()
{
  std::map<string, string> mymap;
  //借用 operator[] 添加新键值对
  mymap["player_01"] = "{\"username\":\"Bear\",\"deviceid\":\"baf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)\"}";
  cout << string("old mymap:") << mymap["player_01"] << endl;
  //借用 operator[] 更新某个键对应的值
  mymap["player_01"] = "{\"username\":\"Horse\",\"deviceid\":\"caf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)\"}";
  cout << "new mymap:" << mymap["player_01"] << endl;


  //借用insert()添加新键值对
  std::pair<string, string> STL = { "Javaplayer_02","{\"username\":\"C++\",\"deviceid\":\"qaf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)\"}" };
  std::pair<std::map<string, string>::iterator, bool> ret;
  ret = mymap.insert(STL);
  cout << "old ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
  //借用 insert() 更新键值对
  mymap.insert(STL).first->second = "node js";
  cout << "new ret.iter = <" << ret.first->first << ", " << ret.first->second << ">" << endl;
  return 0;
}

程序执行结果为:

代码语言:javascript
复制
old mymap:{"username":"Bear","deviceid":"baf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)"}
new mymap:{"username":"Horse","deviceid":"caf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)"}
old ret.iter = <{Javaplayer_02, {"username":"C++","deviceid":"qaf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)"}}, 1>
new ret.iter = <Javaplayer_02, node js>

有关程序中 operator[ ] 和 insert() 成员方法的具体用法,读者可翻阅前面的文章做详细了解,这里不再做过多解释。

显然,map 模板类中 operator[ ] 和 insert() 的功能发生了重叠,这就产生了一个问题,谁的执行效率更高呢? 总的来说,读者可记住这样一条结论:当实现“向 map 容器中添加新键值对元素”的操作时,insert() 成员方法的执行效率更高;而在实现“更新 map 容器指定键值对的值”的操作时,operator[ ] 的效率更高。 至于为什么,有兴趣的读者可继续往下阅读。

向map容器中增添元素,insert()效率更高

首先解释一下,为什么实现向 map 容器中添加新键值对元素,insert() 方法的执行效率比 operator[ ] 更高?回顾程序一中,如下语句完成了向空 mymap 容器添加新的键值对元素:

代码语言:javascript
复制
mymap["player_01"] = "{\"username\":\"Horse\",\"deviceid\":\"caf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)\"}";

此行代码中,mymap["player_01"] 实际上是 mymap.operator[ ](“STL教程”) 的缩写(底层调用的 operator[ ] 方法),该方法会返回一个指向 “STL教程” 对应的 value 值的引用。 但需要注意的是,由于此时 mymap 容器是空的,并没有 "STL教程" 对应的 value 值。这种情况下,operator[ ] 方法会默认构造一个 string 对象,并将其作为 "STL教程" 对应的 value 值,然后返回一个指向此 string 对象的引用。在此基础上,代码还会将 "{\"username\":\"Horse\",\"deviceid\":\"caf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)\"}" 赋值给这个 string 对象。 也就是说,上面这行代码的执行流程,可以等效为如下程序:

代码语言:javascript
复制
typedef map<string, string> mstr;
//创建要添加的默认键值对元素
pair<mstr::iterator, bool>res = mymap.insert(mstr::value_type("player_01", string()));
//将新键值对的值赋值为指定的值
res.first->second = "{\"username\":\"Horse\",\"deviceid\":\"caf8700ac280467fcaf581520dc510ebf1c61c42_3400_MS - 7C02(Micro - Star International Co., Ltd)\"}";

注意,这里的 value_type(K,T) 指的是 map 容器中存储元素的类型,其实际上就等同于 pair<K,T>。

可以看到,使用 operator[ ] 添加新键值对元素的流程是,先构造一个有默认值的键值对,然后再为其 value 赋值。 那么,为什么不直接构造一个要添加的键值对元素呢,比如:

代码语言:javascript
复制
mymap.insert(mstr::value_type("C++", "脱发严重"));

此行代码和上面程序的执行效果完全相同,但它省略了创建临时 string 对象的过程以及析构该对象的过程,同时还省略了调用 string 类重载的赋值运算符。由于可见,同样是完成向 map 容器添加新键值对,insert() 方法比 operator[ ] 的执行效率更高。

更新map容器中的键值对,operator[]效率更高

仍以程序一中的代码为例,如下分别是 operator[ ] 和 insert() 实现更新 mymap 容器中指定键对应的值的代码:

代码语言:javascript
复制
代码语言:javascript
复制
//operator[]
mymap["C++"] = "脱发";
//insert()
std::pair<string, string> STL = { "node","霸王洗发水" };
mymap.insert(STL).first->second = "还是霸王洗发水好";
代码语言:javascript
复制
仅仅从语法形式本身来考虑,或许已经促使很多读者选择 operator[ ] 了。接下来,我们再从执行效率的角度对比以上 2 种实现方式。从上面代码可以看到,insert() 方法在进行更新操作之前,需要有一个 pair 类型(也就是 map::value_type 类型)元素做参数。这意味着,该方法要多构造一个 pair 对象(附带要构造 2 个 string 对象),并且事后还要析构此 pair 对象(附带 2 个 string 对象的析构)。而和 insert() 方法相比,operator[ ] 就不需要使用 pair 对象,自然不需要构造(并析构)任何 pair 对象或者 string 对象。因此,对于更新已经存储在 map 容器中键值对的值,应优先使用 operator[ ] 方法。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 游戏开发司机 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 通过前面的学习我们知道,map 容器模板类中提供有 operator[ ] 和 insert() 这 2 个成员方法,而值得一提的是,这 2 个方法具有相同的功能,它们既可以实现向 map 容器中添加新的键值对元素,也可以实现更新(修改)map 容器已存储键值对的值。 举个例子(程序一):
    • 向map容器中增添元素,insert()效率更高
      • 更新map容器中的键值对,operator[]效率更高
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档