effective STL 读书笔记——第三章:关联容器

条款19:了解相等和等价的区别

相等:一般表示operator==操作符返回true
等价:一般用于关联容器,表示两个对象x和y如果在关联容器c的排序顺序中没有哪个排在另一个之前,一般以Operator<实现,如过x和y是关联容器c,其比较函数为key_comp,则表示x和y等价的表达式如下:

!c.key_comp()(x, y) && !c.key_comp()(y, x);//在c的排序顺序中如果x在y之前它非真,且y在x之前非真 

对于关联容器,你可以定义自己的排序准则——通过定义对象时为容器提供一个仿函数,例如:

class CompareFunc{
public:
    bool operator()(const string &lhs,const string &rhs);
}

set<string,CompareFunc> ssi;

为什么标准库要是用等价的概念,而不是相等来比较两个元素呢?答案在于关联容器是自动有序的,一定是按照某种规则排序的,如果关联容器提供了operator==作为比较相等的函数,那么还需要为排序提供另外一个函数。相反,如果仅仅提供operator<,可以直接使用operator<来实现operator==

条款20:为指针的关联容器指定比较类型

如果为指针的关联容器定义比较函数,则缺省的less将对指针按照字面值进行排序。

条款21: 永远让比较函数对相等的值返回false

实际上是说,不要让关联容器的比较函数对相等的值返回true。让关联容器的比较函数,只提供operator>或者operator<,而不是提供operator<=或者operator>=
例如对于集合set,如果使用operator<=,则可能导致一个值可以被多次插入
set<int, less_equal<int> > s; // s以“<=”排序
s.insert(10);// 第一次插入 10
s.inser(10); // 此处是否会再次插入?

set在第二次插入10时,会去比较是否有等价的值,比较的形式就是:

!less_equal(10,10) && !less_equal(10,10) ;

但是less_equal(10,10) 为true,上述表达式的值肯定是false,因此set认为其集合中没有“10”这个值,所以第二次又对“10”进行插入。同样的,对于multimap和multiset也如果使相等的值返回true,也会有其他问题。

条款22:避免原地修改关联容器的键

对于map和multimap,其键是const的,因此键不能直接修改,只能通过拷贝——删除——插入的方式进行修改
对于set和multiset,元素可能是非const的,也可能是const的(set<const T>/set<T>),但是也只能通过拷贝——删除——插入的方式进行修改

假设set的元素是非const的:
如果你修改了中元素用来进行排序的某个字段的值时,set的迭代器都会失效,因为set发生了重排序

假设set的元素时const的:
其迭代器解引用后得到的是一个const T&,则不可能修改其元素的值,即使使用const_cast或者static_cast也不行,因为他们创建的是临时对象~:

if (i != se.end()) { // 映射掉
const_cast<Employee&>(*i).setTitle("Corporate Deity"); // *i的常量创建一个匿名变量
} 

条款23:考虑用有序vector代替关联容器

1.内存占用:
标准关联容器的典型实现是平衡二叉查找树。一个平衡二叉查找树是一个对插入、删除和查找的混合操作优化的数据结构。对于关联容器的某一个节点,它肯定包含三个指针(迭代器),用来指向左子树、右子树、父节点,这会造成额外的开销。如果容器的元素本省占用的空间比较小,则使用有序vector会更加高效,因为vector除了需要元素本省的空间外,不需要额外存储指针的空间,同时有序的vector可以使用binary_search,lower_bound,equal_range等。

2.内存碎片:
关联容器由于是通过链表的方式实现的,大量使用会导致内存碎片

3.有序vector的缺点
有序vector的缺点是它必须保持有序——插入、删除时必须重新排序,可能会导致重新分配内存,所有的元素都被重新拷贝。因此,本条款实际上是说,当不需要频繁的插入、删除数据的时候,可以使用有序的vector代替关联容器

条款24:当关乎效率时应该在map::operator[]和map-insert之间仔细选择

先看下列代码:

map<int,string> wis;
wis[0] = "0";
wis[1] = "1";

上述代码创建了一个map

条款25:熟悉非标准散列容器

散列容器是关联容器,非标准容器库中,散列表一般有:hash_set、hash_multiset、hash_map和hash_multimap,对应的标准容器散列表是unordered_set、 unordered_multiset、unordered_map和unordered_multimap。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值