(转)《Effective STL》条款24:当关乎效率时应该在map::operator[]和map::insert之间仔细选择

如果你要更新已存在的map元素,operator[]更好,但如果你要增加一个新元素,insert则有优势.

更有效率的”添加或更新“函数(书中的函数我抠了出来~ )

template<typename MapType,
typename KeyArgType,
typename ValueArgType>
typename MapType::iterator
EfficientAddOrUpdate(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))) { // 它的键等价于k...
lb->second = v; // 更新这个pair的值
return lb;
}
else {
typedef typename MapType::value_type MVT;
return m.insert(lb, MVT(k, v)); // 为什么在insert方法中加入lb参数,请参照@3
}
}

当使用map::operator[]插入的元素不存在时,其效率很低,所以才有了上面的函数,它具体怎么个低法这里就不说了,看下面关键点:

@1 lower_bound
原型:iterator lower_bound ( const key_type& x );
返回一个iterator,指向容器中第一个不小于(大于或等于)x的元素。注意,map中的元素是按照key的顺序存储的。
@2 key_comp
key_comp是map的成员,c.key_comp()(x, y)仅当在c的排序顺序中x在y之前时返回真
@3 关于map::insert
给insert指定一个position参数,使其效率显著提升,这也是使用lower_bound查找而不用find查找的原因,find查找不到返回的iterator指向map::end。

时间: 2024-11-14 12:43:56

(转)《Effective STL》条款24:当关乎效率时应该在map::operator[]和map::insert之间仔细选择的相关文章

Effective STL 条款1:仔细选择你的容器

条款1:仔细选择你的容器 了解各种容器的实现方法,知道各种容器的内存管理方式.各种操作所对应的底层操作,然后根据需要选择恰当的容器. 对于容器的分类: 标准STL序列容器:vector,string,deque和list 标准STL关联容器:set,multiset,map和multimap 非标准序列容器:slist(单向链表)和rope(重型字符串--不懂) 非标准关联容器:hash_set,hash_multiset,hush_map和hash_multimap vector == str

effective stl 条款18:避免使用vector&lt;bool&gt;

做为一个STL容器,vector<bool>确实只有两个问题.第一,它不是一个STL容器.第二,它并不容纳bool.除此以外,就没有什么要反对的了 . 在这些要求中有这样一条:如果c是一个T类型对象的容器,且c支持operator[],那么以下代码必须能够编译:T *p = &c[0]; // 无论operator[]返回什么,// 都可以用这个地址初始化一个T*换句话说,如果你使用operator[]来得到Container<T>中的一个T对象,你可以通过取它的地址而获得

Effective STL 条款3

确保容器中的对象拷贝正确而高效 在使用STL模板的时候,我们必须想到有关拷贝的问题.如果STL中存储的是我们自定义类型.可能会发生以下几个问题: 首先 为了避免拷贝过程成为程序运转的瓶颈,我们选择存储自定义的指针.但是,这里容易出现野指针的问题,所以我们需要使用智能指针shared_pre来避免. 接着 如果存储类型为基类,此时我们存储派生类,则会发生截断现象,即只copy了基类部分,而派生类部分丢失. 最后 相对于数组来说,vector有它独到的有点,最明显的就是长度的动态增长.

effective stl 条款15 小心string实现的多样性

实际上每个string实现都容纳了下面的信息: ● 字符串的大小,也就是它包含的字符的数目. ● 容纳字符串字符的内存容量.(字符串大小和容量之间差别的回顾,参见条款14.) ● 这个字符串的值,也就是,构成这个字符串的字符 另外,一个string可能容纳 ● 它的配置器的拷贝.对于为什么这个域是可选的解释,转向条款10并阅读关于这个古怪的管理分配器的规则.依赖引用计数的string实现也包含了 ● 这个值的引用计数 ● string对象的大小可能从1到至少7倍char*指针的大小.● 新字符串

Effective C++ 条款24

若全部參数皆需类型转换,请为此採用non-member函数 我们直奔主题 假设你定义一个有理数类例如以下 class Rational{ public: Rational(int numerator=0, int denominator=1);//非explicit.同意隐式转换 const Rational operator*(const Rational& rhs); ....................... }; result=oneHalf*2;//正确.相当于oneHalf.op

Effective C++ 条款24 若所有参数皆需类型转换,请为此采用non-member函数

1. 通常,将只接受拷贝构造函数声明为explict是一个不错的主意,因为这可以避免自动的隐式类型转换所带来的错误,但有些情况下,使类支持隐式类型转换是可行的,例如自定义的数值类型: class Rational{ public: Rational(int numerator=0,int denominator=1); int numerator()const; int denominator()const; private: int numerator; int denominator; }

Effective C++ 条款21必须返回对象时,别妄想返回其reference

1. 虽然一般情况下传参使用const-by-reference-to-const比较好,但返回值有时必须是对象而不是引用: 当reference绑定到函数内创建的局部对象时,函数调用结束后引用绑定在一个不存在的对象; 当reference绑定到堆内存对象时,函数调用后比较容易忽略内存释放,特别对于以下表达式:w=x*y*z.如果operator*返回指向堆内存的引用,那没内存泄露是必然的; 当reference绑定到函数内部创建的static对象时,对于以下表达式if(a*b==c*d)由于返

effective c++ 条款12:复制对象时勿忘其每一个成分

记住:拷贝函数应该确保复制"对象内的所有成员变量"及"所有父类成分".不要尝试以某个拷贝函数实现另一个拷贝函数.应该将共同机能放进第三个函数中,并由两个拷贝函数共同调用. 下面是一个类实现了自己的拷贝函数,一起正常. void logCall(const string& funcName): class Customer { public: ... Customer(const Customer& rhs); Customer& operat

C++学习书籍推荐《Effective STL(英文)》下载

百度云及其他网盘下载地址:点我 作者简介 Scott Meyers is one of the world's foremost authorities on C++, providing training and consulting services to clients worldwide. He is the author of the best-selling Effective C++ series of books (Effective C++, More Effective C+