Effective STL --关联容器

高效STL—关联容器

标准关联容器中最重要的就是基于等价而不是相等。比如对于基本的函数库有find函数,但是对于set关联容器也是有find成员函数的。因为标准关联容器保持有序,所以每一个容器必须有一个定义了怎么保持东西有序的比较函数(默认是less)。等价是根据这个比较函数定义的,所以标准关联容器的用户只需要为他们要使用的任意容器指定一个比较函数

必须为指针的关联容器指定比较类型

一定要明确对于一个容器来说,容器内的迭代器是存入该容器对象的指针,比如一个关联容器存入指针类型,那么使用这个容器的迭代器的取值仍然是该对象的指针。比如:

Set<string*> ssp;

Ssp.insert(newstring(“adfa”));

Ssp.insert(newstring(“bdfa”));

Ssp.insert(newstring(“cdfa”));

Ssp.insert(newstring(“ddfa”));

然后写一段程序希望打印字符串;

For(set<string*>::const_iteratorI = ssp.begin();i!=ssp.end();i++)

Cout<<*i<<endl;

看到的是四个十六进制的数,*i不是一个string ,它是一个string的指针。如果将*i修改为**i,可能得到正确的答案。但是有可能不是,因为set中排序的标志是按照set中元素的性质来的,也就是按照string指针来排序的。

Set<string*,less<string*>,allocator<string*>>ssp;

如果想要string*指针以字符串值确定排序被存储在set中,不能使用默认的比较仿函数。需要自定义,它的对象带有string*指针并按照指向的字符串值来进行排序。也就是为关联容器定义自己的比较函数。

避免原地修改set和multiset的键

所有的关联容器,set和multiset保持他们的元素有序,这些容器的正确行为依赖于他们保持的有序。如果你修改了关联容器里的一个元素的值,新值可能不在正确的位置,而且那将破坏容器的有序性。不要修改set和map中的键值部分,不然会影响set的排序

如果你改变关联容器里的元素,必须确保不改变键值部分,这会影响有序性的元素部分。对于非键值部分,可以随意修改。如果想修改关联容器中的元素,最好的办法就是将这个待修改的元素赋值给临时变量,然后在容器中删除这个元素,将修改后的临时变量插入到容器中。

使用有序的vector来代替关联容器,可以这么认为,对于一个vector,使用的是连续内存,对于一个关联容器,里面还有几个指针,一个页面可以存储比关联容器更多的对象,而且不会造成却也中断。当在vector中存储对象没有开销,但是对于关联容器有三个指针或两个指针和一个int。如果我们的数据结构足够大,他们可以分成多个内存页面,但是vector比关联容器需要的页面要少,因为关联容器给每个对象附加了三个之后做呢。

在有序vector中存储数据很有可能比在标准关联容器中保存相同的数据消耗更少的内存,当页面错误值得重视的时候,在有序vector中通过二分查找法查找可能比在一个标准关联容器中查找更快。但是一定要明白使用vector代替关联容器的前提。

字考虑效率的时候,在map::operator[]和map.insert()之间是有区别的,对于一个map容器,插入一个元素的操作:

Map<int,object>m;

M[1] = 1.50;

表达式m[1]是m.operator[](1)的简化,所以这是一个map::operator[]的调用。那个函数必须返回一个object的引用,因为m的映射类型是object。在这里,m里面没有任何东西,所以键1在Map里没有入口。一次operator[]默认构造一个object来作为关联到1的值,然后返回到那个object的引用。最后,object成为赋值目标,被赋值的值是1.50。整个过程就是先默认构造一个object,然后我们立即赋给它新值。如果用想要的值构造object比默认构造object然后进行赋值显然更高效,我们就应该用直截了当的Insert调用来替换operator[]的使用。

Typedefmap<int,object> obj_map;

m.insert(obj_map::value_type(1,1.50));

上述代码利用了value_type,对于map和multimap这个很重要,容器元素的类型总是某种pair.

所以,当使用增加功能时,Insert比operator[]更高效。但是我们做更新时,情形正好相反。

M[k] = v; //使用operator[]来把k的值更新为v

m.insert(obj_map::value_type(k,v)).first->second= v; //使用insert来把v的值更新为v

insert的调用需要obj_map::value_type类型的实参(pair<int,object>),所以当我们调用Insert时,我们必须析构和构造一个那种类型的对象。会造成一个析构函数和构造函数的调用,operator[]没有使用pair对象,所以没有构造和析构pair和object。

综述:当给map添加一个元素时,我们断定insert比operator[]好;当更新已经在map里的元素值时operator[]更好。

时间: 2024-10-13 23:44:21

Effective STL --关联容器的相关文章

Effective STL: 不同容器删除元素的方法

不同容器删除元素的方法 去除一个容器中有特定值的所有对象: 如果容器是vector.string或deque,使用erase-remove惯用法. 如果容器是list,使用list::remove. 如果容器是标准关联容器,使用它的erase成员函数. 去除一个容器中满足一个特定判定式的所有对象: 如果容器是vector.string或deque,使用erase-remove_if惯用法. 如果容器是list,使用list::remove_if. 如果容器是标准关联容器,写一个循环来遍历容器元素

STL - 关联容器

关联容器中的元素是按关键字来保存和访问的.与之相对,顺序容器是按它们在容器中的位置和顺序保存和访问的. 关联容器也是模板.为了定义一个map,我们必须指定关键字和值的类型. 与顺序容器类似,可以对一个关联容器的元素进行列表初始化. 按关键字有序保存元素 map 当从map中提取一个元素时,会得到一个pair类型的对象.简单来说,pair是一个模板类型,保存两个名为first和second的公有数据成员. set find调用返回一个迭代器,如果给定关键字存在,迭代器指向该关键字.否则,find返

STL 笔记(二) 关联容器 map、set、multimap 和 multimap

STL 关联容器简单介绍 关联容器即 key-value 键值对容器,依靠 key 来存储和读取元素. 在 STL 中,有四种关联容器,各自是: map 键值对 key-value 存储,key 不可反复,即一个 key 仅仅能相应一个 value, 相应头文件<map> multimap 键值对 key-value 存储,key 能够反复,即一个 key 能够相应多个 value, 相应头文件<map> set 仅仅有 key, key 不可反复,相应头文件<set>

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

STL 笔记(二): 关联容器 map、set、multimap 和 multimap

STL 关联容器简介 关联容器即 key-value 键值对容器,依靠 key 来存储和读取元素.在 STL 中,有四种关联容器,分别是: map 键值对 key-value 存储,key 不可重复,即一个 key 只能对应一个 value, 对应头文件<map> multimap 键值对 key-value 存储,key 可以重复,即一个 key 可以对应多个 value, 对应头文件<map> set 只有 key, key 不可重复,对应头文件<set> mult

Effective STL 第1条:慎重选择容器类型

C++提供了几种不同的容器供我们选择,这里简单回顾一下: 1.标准STL序列容器:vector.string.deque和list. 2.标准STL关联容器:set.multiset.map.和multimap. 3.非标准序列容器slist和rope.slist是一个单向链表,rope本质上是一"重型"string. 4.非标准关联容器hash_set.hash_multiset.hash_map和hash_multimap. 5.vector<char>作为string

【STL 基本容器】

1.顺序容器与关联容器 c++中有两种类型的容器:顺序容器和关联容器,顺序容器主要有:vector.list.deque等.其中vector表示一段连续的内存地址,基于数组的实现,list表示非连续的内存,基于链表实现.deque与vector类似,但是对于首元素提供删除和插入的双向支持.关联容器主要有map和set.map是key-value形式的,set是单值.map和set只能存放唯一的key值,multimap和multiset可以存放多个相同的key值. 2.顺序容器 (1) vect

effective stl(容器部分总结)

还是很喜欢effective部分的书,看了好几遍,这里把stl中和容器相关的一些基本的注意的点进行介绍总结,之后对迭代器等进行总结 1 对序列容器中需要逐个删除的时候,不能像关联容器那样事先对迭代器进行++操作,因为删除一个迭代器,会使他自己无效,后面的迭代器也无效,所以应该保存删除erase返回的下一个指针的值.而关联容器中并不会导致后面的迭代器无效的情况 2 在stl中如果对容器内对象使用了new操作,一定要释放掉,因为析构函数没办法完成,这里最好使用智能指针,但是不要使用auto_ptr的

STL源码剖析---关联容器

标准关联容器分为set和map两大类,包括multiset和multimap,这些容器的底层机制都是RB-tree.标准之外的关联容器有hashtable 以及以此hash table为底层机制而完成的hash_set(散列集合) hash_map(散列映射表) hash_multiset  hash_multimap. 序列和关联容器各自的内部关系是内含的,例如heap内含一个vector,priority_quehe内含一个heap,stack和queue都内含一个deque,set/map