readme
我们从两个“灯下黑”的问题开始。
提问1:如何向一个map容器中添加一个元素,有什么区别?
是否有第三种方法本人不晓得,但是map::operator[]和map::insert是两种最常用的方法。它们都很常见,保证任何一个c++程序员都用过很多次,多到忽略了思考它们是否有区别。
提问2:如何更新一个map容器中的某个元素?
map::operator[]是最常用的方法,map::insert其实也可以,但是绕了一个弯。
这篇博客回答了这两个“灯下黑”的问题。
测试程序
//common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include <iterator>
#include <sys/time.h>
using namespace std;
#endif
//insert_vs_index.cpp
#include "common.h"
class testclass
{
public:
testclass();
testclass(const double& other);
testclass& operator=(const double& other);
~testclass() {};
double get_value()
{
return m_testdouble;
};
private:
double m_testdouble;
};
testclass::testclass()
{
printf("in testclass::testclass()\n");
m_testdouble = 0;
}
testclass::testclass(const double& other)
{
printf("in testclass(double testclass)\n");
m_testdouble = other;
}
testclass& testclass::operator=(const double& other)
{
printf("in testclass& testclass::operator=(double testvalue)\n");
m_testdouble = other;
return *this;
}
int main(void)
{
{
map<int, testclass> testmap;
printf("operation start\n");
printf("add element by index\n");
testmap[1] = 100.1;
printf("add element by insert\n");
testmap.insert(make_pair(2, 100.2));
printf("operation finish\n");
}
{
map<int, testclass> testmap;
printf("operation start\n");
printf("map prepare start\n");
testmap[1] = 100.1;
testmap[2] = 100.2;
printf("map prepare finish\n");
printf("add element by index\n");
testmap[1] = 100.3;
printf("add element by insert\n");
auto testpair = testmap.insert(make_pair(2, 100.4));
if (!testpair.second)
{
printf("failed in testmap.insert(make_pair(2, 100.4));\n");
}
testpair.first->second = 100.4;
printf("testmap[2]: %f\n", testmap[2].get_value());
printf("operation finish\n");
}
return 0;
}
编译和执行结果
g++ -o insert_vs_index insert_vs_index.cpp -O0 -g -Wall -std=c++11
./insert_vs_index
operation start
add element by index
in testclass::testclass()
in testclass& testclass::operator=(double testvalue)
add element by insert
in testclass(double testclass)
operation finish
operation start
map prepare start
in testclass::testclass()
in testclass& testclass::operator=(double testvalue)
in testclass::testclass()
in testclass& testclass::operator=(double testvalue)
map prepare finish
add element by index
in testclass& testclass::operator=(double testvalue)
add element by insert
failed in testmap.insert(make_pair(2, 100.4));
in testclass& testclass::operator=(double testvalue)
testmap[2]: 100.400000
operation finish
关于map::insert的多一点介绍
map::insert向map容器中添加元素,它有一个返回值。map::insert会返回一个pair<first, second>对象。如果insert的元素事先在map中不存在,first变量是一个指向插入后元素的迭代器;如果insert的元素事先map中已经存在,first变量是指向map中相同键值对应的元素的迭代器。至于second变量,代表insert操作是否成功,如果元素事先在map中不存在second变量为true,如果元素事先已经在map中存在second变量为false。
如何向一个map容器中添加一个元素,有什么区别?
map::operator[]和map::insert两种方法都可以实现向map容器中添加一个元素的目的。至于它们之间的区别,这里需要分类讨论:被添加的元素事先在map中不存在;被添加的元素事先在map中已存在。
被添加的元素事先在map中不存在
map::operator[]会在map中创建一个元素(k, v),其中v通过默认构造函数创建。map::operator[]返回v的引用,紧接着v被赋予为新值。听上去已经有点冗余了。
而map::insert高效很多,直接使用目标值构造一个v,不需要赋值操作。
结论就是如果被添加的元素事先在map中不存在,map::insert的效率要好于map::operator[]。
被添加的元素事先在map中存在
map::operator[]会返回一个引用,指向map中相同k对应的v,之后用目标值更新原来的v。
而map::insert就复杂了,如果元素事先已经在map中存在,map::insert会以失败告终,详见测试代码执行结果打印出来的“failed in testmap.insert(make_pair(2, 100.4));”。map::insert如果想要达到更新的目的,需要根据insert操作的结果作出进一步赋值操作。这里隐含着pair对象的构建和析构,是相较于map::operator[]多余的操作。
结论就是如果被添加元素事先在map中存在,map::operator[]的效率要好于map::insert。