6 STL容器

6 STL容器

6.1  容器的共通操作



6.2 vector——<vector>

1、vector的容量(可由成员函数capacity()返回)很重要,如果超过就要重新配置内部存储器(很耗时),且和vector相关的所有reference、pointer、iterator都会失效。

std::vector<int> v; v.reserve(80); //申请容量,最好不要使用std::vector<int> v(80);因为后者要求元素提供默认构造函数,而前者无需初始化。

注意vector的容量不可缩减。一种方法为std::vector<T>  tmp(v); v.swap(tmp);

 

2、几个需要注意的操作函数

vector<Elem> c(n, elem); //产生一个大小为n的vector,每个元素为elem,类似于c.assign(n,elem);

c.at(idx);  //返回索引idx指向的元素。如果越界,抛出out_of_range异常。类似于c[idx],但后者不进行范围检查,越界会出现未定义行为。

c.front();与c.back();  //分别返回第一个/最后一个元素,若c为空,印发未定义行为。

安插和移除元素:迭代器必须指向合法位置,区间起始位置不能在结束位置之后,决不能从空容器移除元素。

c.insert(pos, elem);  //在pos位置插入一个elem副本

c.insert(pos, n, elem);  //在pos位置插入n个elem副本

c.insert(pos, beg, end);

c.resize(num); //将元素数量改为num(若size()变大,多出来的新元素以默认构造函数构造)

c.clear(); //清空所有元素

c.pop_back(); //注意无返回值,且c不能为空

 

4、异常处理

push_back()提供强保证, pop_back(),和swap()不抛出异常。

如果元素的拷贝(copy构造函数和assignment操作符)不抛出异常,所有操作提供强保证或不抛出异常。


6、class vector<bool>

内部一个bit存储一个元素,动态大小的位域。(如果需要静态大小的位域,应当使用bitset)

c.flip(); //所有bool元素取反

c[idx].flip();  //将索引idx的bit元素取反,注意其中使用了proxy的技巧


6.3 deque——<deque>

2、操作函数:

不提供容量操作(capacity()和reserve());

具有push_front() 和pop_front()


6.4 list——<list>

1、特性

不支持随机存取;安插和删除较快,且不会造成point、reference、itrerator失效;显然不需要提供容量、空间重新分配等操作函数。


2、操作函数:

增加c.remove(val) ;   //移除所有值为val的元素

增加remove_if(op);       //移除所有造成op(elem)结果为ture的元素

增加splice(铰接)函数:


注意:对于c.unique(op);任何一个元素elem,设其前一个元素为e,若op(elem, e);为true,则移除elem。注意op不能再函数调用过程中改变状态。


3 异常处理

几乎所有操作提供强保证。除了:

赋值运算和成员函数sort()只提供基本保证;

merge(), remove(), remove_if(), unique()要求元素间的比较(operator==或判断式predicate)不抛出异常,才能提供强保证。


6.5 set和multiset——<set>

1、特性:

通常以平衡二叉树实现;自动排序造成不能直接改变元素值,不提供直接存取元素的任何操作函数。


2、操作函数:

c(op);   //以op为排序准则,产生一个空的set

特殊的搜索函数:


注意:equal_range()返回一个pair。

元素的安插和移除:


//set的insert接口
pair<iterator, bool> insert(const value_type& elem); //若该值已存在,则返回bool值为0(插入失败)
iterator insert(iterator pos_hint, const value_tyoe& elem);

//multiset的insert接口
iterator insert(const value_tyoe& elem);
iterator insert(iterator pos_hint, const value_tyoe& elem);

注意:set、map等不支持insert(pos,  num, elem);和insert(pos, begin, end); 而vector、deque、list不支持insert(begin, end); string所有形式都支持。

注意:erase()无返回值,与vector不同,这主要是对于关联式容器,返回后继元素颇为耗时。


3、异常处理
多重元素安插操作不能提供强保证,但单一元素安插操作和多元素删除操作提供强保证。

如果元素排序准则的复制/赋值操作会抛出异常,swap()也会抛出异常。

 

6.6 map和multimap——<map>

1、要求:key/value可复制且可赋值,对排序准则而言,key可比较。

 

2、操作函数:

包含与set类似的所有函数。

//注意1:c.insert(elem);安插key/value时,有以下三种方法
std::map<std::string, float> coll;
//使用value_type,可避免隐式类型转换
coll.insert(std::map<std::string,float>::value_type("abc",2.2);
//使用pair
coll.insert(std::pair<std::string, float>("abc", 2.2)); //隐式转换
coll.insert(std::pair<const std::string, float>("abc", 2.2));  //显示转换
//使用make_pair()
coll.insert(std::make_pair("abc", 2.2));

注意2:find(elem)中elem只能是key,不能使value,且find(key)速度较快。

 

//注意3:移除指定元素value的正确方法(对于key,调用coll.erase(key)即可)
for(pos = coll.begin(); pos!=coll.end(); ){
	if(pos->second == value){
		coll.erase(pos++); //因为一旦erase(pos)之后,当前pos失效。且对于关联式容器,erase()不返回后继。
	}else{
		++pos;
	}
}


3、将map视为关联式数组

关联式容器并不提供元素的直接存取,必须使用迭代器,但是map是个例外。

m[key]   返回一个reference,指向键值为key的元素。如果该元素尚未存在,就安插该元素。(注意新元素的value必须有默认构造函数)

例:对于coll["otto"] = 7.7;如果不存在这个key,则向容器中插入"otto"/float(),之后将7.7赋值给这个新元素。 

这提供了修改key的方法(一般采用先插入newkey,再删除oldkey):

coll["newkey"] = coll["oldkey"]; coll.erase("oldkey");   //假设"oldkey"这个键值已存在于容器中。


6.8 实现reference语义

对容器中的元素采用引用计数型智能指针(如boost中的shared_ptr<>)。


6.9 各种容器的使用时机

元素被移除时,deque可以自动缩减内存(因为它使用多个区块)。

如果需要关联式数组,就采用map;如果需要字典结构,就采用multimap。

注意:关联式容器每安插一个新元素,都进行一次排序,速度不及序列式容器的做法:先安插所有元素,再使用sort进行一次完全排序。


6.10 细说容器中的类型和成员

1、容器中的类型

value_type:元素类型,对于map和multimap是pair<const key-type, value-type>

reference, const_reference, iterator, const_iterator, ......


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值