假定我们有一个Widget类,它支持默认构造函数,并根据一个double值来构造和赋值:
class Widget {
public:
Widget();
Widget(double weight);
Widget& operator=(double weight);
...
};
// 初始化
map<int, Widght> m;
m[1] = 1.50;
map::operator[]的设计目的是为了提供添加和更新的功能。即对于map<K,V> m;表达式m[k]=v;的意思是:检查键k是否已经在map中了。如果没在,就加入,并以v作为相应的值;如果在,则更新值为v。
1 添加
m[1] = 1.50在功能上等同于:
typedef map<int, Widget> IntWidgetMap;
pair<IntWidgetMap::iterator, bool> result = m.insert(IntWidgetMap::value_type(1, Widget()));
result.first->second = 1.50;
换成对insert的直接调用:
m.insert(IntWidgetMap::value_type(1, 1.50));
可以看出,使用map::insert代替map::operator[]节省了3个函数调用:
(1) 默认构造临时Widget对象
(2) 析构该临时对象
(3) 调用Widget的赋值操作符(m[1] = 1.50)
这些函数调用的代价越高,节省的开销越大。
2 更新
情况与添加相反
// operator[]
m[k] = v;
// insert
m.insert(IntWidgetMap::value_type(k, v)).first->second = v;
insert调用需要IntWidgetMap::value_type类型的参数(即pair<int, Widget>),当我们调用insert时,必须构造和析构pair和Widget。而operator[]不使用pair<int, Widget>,没有这些开销。
所以,结论就是:当向map中添加元素时优先使用insert;当向map中更新元素时优先使用operator[]。