条目二十四《当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择》

当效率至关重要时,应该在map::operator[]map::insert之间仔细做出选择。如果要更新一个已有的映射表元素,则应该优先选择operator[];但如果要添加一个新的元素,那么最好还是选择insert

下面来分析为什么是这样子的。

首先先说明,下面两个式子是等价的:

map<int, int> ss;
ss[1]=2 //式子1
ss.insert(pair<int, int>(1, 2)) //式子2

咋一看上去,式子1比式子2简洁很多,但二者在不同情况下性能是不一样的。

map::operator[] 返回一个引用,它指向与k相关联的值对象。然后v被赋给该引用(operator[]返回的那个引用)所指向的对象。如果键k已经有了相关联的值,则该值被更新。如果k还没有在映射表中,那就没有operator[]可以指向的值对象。在这种情况下,它使用值类型的默认构造函数创建一个新的对象,然后operator[]就能返回一个指向该新对象的引用了。

对于第二种情况,就是说,如果map::operator[]的是一个不存在map的值,会先调用默认构造函数创建一个临时对象,然后对得到的临时对象的引用的对象调用赋值函数(修改v),最后调用析构函数析构临时对象。

你看这里会经历三个函数的调用哦,所以如果是频繁的经历这个过程,肯定会对性能有影响的。

pair<map<int, TesyObj>:: itrator, bool> iesult = m.insert(map<int, TesyObj>>:: value_type(1, TestObj())
result.first->second=5

上面的代码例子就是上面说的过程囖。

再看map::insert的情况。

m.insert(map<int, TesyObj>::value_type(1, 5))

你看,对于map::insert来说,插入不存在的值,省略了三个函数的调用啊。

所以针对添加元素insertoperator[]更高效。

再来看对于更新元素的情况。

m[k]=v
m.insert(map<int, TesyObj>::value_type(k, v)).first->second=v

从感官上看,前者肯定比后者简洁舒服啊。不过我们要看的是效率。

后者比前者多了对pair对象的构造析构,而且在构造pair时又对v(TestObj)对象构造,析构pair时又对v析构,所以前者效率更高。。。

最后看个例子吧,一个鱼与熊掌兼得的实现:

![](file:///storage/emulated/0/Pictures/ddReader/1547478826150.png)

条目二十四《当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择》的更多相关文章

  1. (C/C++学习笔记) 二十四. 知识补充

    二十四. 知识补充 ● 子类调用父类构造函数 ※ 为什么子类要调用父类的构造函数? 因为子类继承父类,会继承到父类中的数据,所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程. ...

  2. 《条目二十九:对于逐个字符的输入请考虑istreambuf_iterator》

    <条目二十九:对于逐个字符的输入请考虑istreambuf_iterator> 1.使用: ifstream inputfile("xxxx"); string fil ...

  3. Bootstrap<基础二十四> 缩略图

    Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ...

  4. WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的?

    原文:WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的? 服务端只有抛出FaultException异常才能被正常地序列化成Fault消息,并实现向客户 ...

  5. VMware vSphere 服务器虚拟化之二十四 桌面虚拟化之手动池管理物理机

    VMware vSphere 服务器虚拟化之二十四 桌面虚拟化之手动池管理物理机 VMwareView手动池可以管理物理计算机 说明: 环境基于实验二十三 1.准备一台Windows 7的物理计算机名 ...

  6. 二十四. Python基础(24)--封装

    二十四. Python基础(24)--封装 ● 知识结构   ● 类属性和__slots__属性 class Student(object):     grade = 3 # 也可以写在__slots ...

  7. 条目二十八《正确理解由reverse_iterator的base()成员函数所产生的iterator的用法》

    条目二十八<正确理解由reverse_iterator的base()成员函数所产生的iterator的用法> 迭代器的种类一共有四种,上面已经说过了.这里就不再次写出来. 这一个条目主要是 ...

  8. 条目二十六《iterator优先于const_iterator、reverse_iterator以及const_reverse_iterator》

    条目二十六<iterator优先于const_iterator.reverse_iterator以及const_reverse_iterator> 这几个东西不是类型来的,而是不同的类,所 ...

  9. 微信小程序把玩(二十四)toast组件

    原文:微信小程序把玩(二十四)toast组件 toast消息提示框,可用在提示一些信息,比如清楚缓存给用户一个友好的提示!或操作一些请求不想让用户有什么操作,toast也可以做到因为toast显示时其 ...

随机推荐

  1. Opencv3 图片膨胀与腐蚀

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

  2. [C++] Variable storage space

    Variable storage space

  3. csv乱码

    可能:iconv转码导致,本身已经是GBK,又进行了GBK转码

  4. OracleBulkCopy 修正帮

    using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Refle ...

  5. Linux-shell-算术运算{expr、bc、dc、(( ))和[ ]}

    Linux-shell-算术运算{expr.bc.dc.(( ))和[ ]} 摘自: https://www.cnblogs.com/snowsolf/p/3325235.html 在Linux下做算 ...

  6. Grunt 与WebStrom 集成

    为了不想使用命令行的方式开着grunt,打算将Grunt命令集成WebStrom 中 . 1.将配置好的Gruntfile文件放到项目的根目录下.. 2.File-setting-Extental T ...

  7. 深入理解linux的权限设置和SUID,SGID以及粘滞位

    我们知道文件的权限可以用三个八进制数字表示.其实文件的权限应该用四个八进制来表示,不过用 ls -l 命令时,只显示三个罢了.那个没有显示的八进制数字其实是第一个,它用来设定一些特殊权限.这个八进制数 ...

  8. Alpha冲刺(十)

    Information:   队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Details: 组员1(组长)柯奇豪 过去两天完成了哪些任务 本人负责的模块(共享编辑)的前端 ...

  9. 【小梅哥FPGA进阶教程】第十一章 四通道幅频相可调DDS信号发生器

    十一.四通道幅频相可调DDS信号发生器 本文由山东大学研友袁卓贡献,特此感谢 实验目标 实现多通道可调信号发生器 实验平台 芯航线FPGA核心板.ADDA模块 实验现象 实现基于FPGA的多通道可调信 ...

  10. 学习python3

    定义一个函数 你可以定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 (). 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定 ...