Effective STL 24 Choose carefully between map::operator[] and map::insert

来源:互联网 发布:淘宝号信誉等级查询 编辑:程序博客网 时间:2024/05/23 19:21

I. if the key 1 isn’t yet in the map

m[1] = 1.50;

is functionally equivalent to this:

typedef map<int, Widget> IntWidgetMap;pair<IntWidgetMap::iterator, bool> result =     m.insert(IntWidgetMap::value_type(1, Widget()));result.first->second = 1.50;

more effecitve way is:

m.insert(IntWidgetMap::value_type(1, 1.150));

so, the more expensive the cost of assignment of the value part of the pair, the more you save by using map::insert instead of map::operator[].

II. when an equivalent key is already in the map.

// use operator[] to update k's value to be vm[k] = v;
// usinsert to update k's value to be vm.insert(IntWidgetMap::value_type(k, v).first->second = v;

The call to insert requires an argument of type IntWidgetMap::value_type (pair<int, Widget>), so when we call insert, we must construct and destruct an object of the type. That costs us a pair constructor and destructor. That, in turn, entails a Widget construction and destruction, because a pair<int, Widget> itself contains a Widget object. operator[] uses no pair object, so it constructs and destructs no pair and no Widget.

III. Efficient add-or-update functionality.

template<typename MapType, typename KeyArgType, typename ValueArgType>typename KeyArgType::iteratorefficientAddOrUpdate(MapType& m, const KeyArgType& k, const ValueArgType& v) {typename MapType::iterator lb = m.lower_bound(k);if (lb != m.end() && !(m.key_comp()(k, lb->first))) {    lb->second = v;    return lb;} else {    // MapType::value_type is a dependent type, you are required to precede     // it with the word typename. otherwise, it will be confused with static    // members;    typedef typename MapType::value_type MVT;    return m.insert(lb, MVT(k, v));    }}

Note: why don’t use MapType::key_type and MapType::mapped_type instead the type parameters KeyArgType and ValueArgType.

map<int, Widget> m;class Widget{public:    ...    Widget& operator=(double weight);    ..};efficientAddOrUpdate(m, 10, 1.5);

In this case, the template above deduces that ValueArgType is double, and the body of the function directly assigns 1.5 as a double to the Widget associated with the key 10. That’s accomplished by invocation of Widget::operator=(double). If we had used MapType::mapped_type as the type of efficientAddOrUpdate’s third parameter, we’d have converted 1.5 to a Widget at the point of call, and we’d thus have paid for a Widget construction (and subsequent destruction) we didn’t need.

原创粉丝点击