第 9 章 顺序容器

       标准库定义了三种顺序容器类型:vector、list和deque(双端队列“double-ended queue”),还提供了三种容器适配器(非迭代器,之前一眼以为是迭代器):stack、queue和priority_queue。

9.1、顺序容器的定义

       为了使程序更清晰、简短,容器类型最常用的构造函数是默认构造函数

       容器构造函数:(1)C<T> c;默认构造函数;(2)C<T> c(c2);创建容器c2的副本c,c和c2必须具有相同的容器类型;(3)C c(b,e);创建c,其元素是迭代器b和e标示的范围内元素的副本(其中第二个参数(指针,即迭代器)提供停止复制的条件),但如vector赋值给stack不可以···stack方法少很多···没有begin方法。(4)C<T> c(n,t);用n个值为t的元素创建容器c,其中t必须是容器类型C的元素类型值或者是可转换为该类型的值。只适用于顺序容器,顺序容器适配器不行···,容器大小n可以使常量或者常量表达式。(4)C<T> c(n);创建n个值初始化元素的容器c,也只适合顺序容器。

       容器元素类型必须满足:(1)元素类型必须支持赋值运算;(2)元素类型的对象必须可以复制。

       如果类A没有默认构造但提供了需要一个int型形参的构造函数,那么vextor<A> empty;可以;vextor<A>bad(10);这是不可以,会产生运行错误;vextor<A> ok(10,1);这是可以,因为有这类型构造。对于C c(b,e);用迭代器的方法,有没有构造函数都一样,它应该是借助复制实现的吧···。

       vector<vector<string> > lines;必须用空格隔开两个相邻的”>”符号,用于表示两个分开的符号,否则系统会认为是>>单个符号,为右移符号从而导致编译错误VS貌似不隔开也可以···

9.2、迭代器和迭代器范围

       迭代器的关系操作符只适用于vector和deque容器,因为只有这两种容器为其元素提供快速、随机的访问。

       list容器的迭代器既不支持算术运算(加法或减法),也不支持关系运算(<=、<、>=、>),它只提供前置和后置的自增、自减运算以及相等(不等)运算

9.2.1、迭代器范围

       C++语言使用一对迭代器标记迭代器范围:迭代器范围遵循左闭右开。很好想,因为右边有可能指向最后一个元素的下一位置,所以用左闭右开是有道理的。(1)当first和end迭代器相等时,迭代器范围为空;

9.3、顺序容器的操作

       逆序迭代器reverse_iterator,在该逆序迭代器上作++操作运算将指向容器中的前一个元素。用法如:list<string>::iterator iter;。difference_type类型表示足够存储两个迭代器差值的有符号整型,可为负数。

9,3,2、begin和end成员

       c.rend()返回一个逆序迭代器,它指向容器c的第一个元素前面的位置

9.3.3、在顺序容器中添加元素

       c.insert(p,t)在迭代器p所指向的元素前面插入值为t的新元素。返回指向新添加元素的迭代器。c.insert(p,n,t);在迭代器p所指向的元素前面插入n个值为t的新元素,返回void类型。c.insert(p,b,e);在迭代器p所指向的元素前面插入由迭代器b和e所标记的范围内的元素,返回void类型。

       push_back(t)(尾部添加)和push_front(t)(前端添加)只适用于list和deque容器类型。

       在vector容器中添加元素可能导致整个容器的重新加载,使得原先的迭代器失效

9.3.5、容器大小的操作

       c.resize(n)或(n,t)调整容器c的长度大小,使其能容纳n个元素,如果n<c.size(),则删除多出来的元素,否则添加采用初始化的新元素或添加元素值为t。resize操作可能使迭代器失效。

9.3.6、访问元素

       如果容器非空,那么容器类型的front和back成员将返回容器内第一个或最后一个元素的引用。c[n]和c.at(n)只适用于vector和deque容器,如果下标越界则该操作未定义,会抛出out_of_range异常。

9.3.7、删除元素

       c.erase(p)删除迭代器p所指向的元素。返回一个迭代器,它指向被删除元素后面的元素。如果p指向容器最后一个,则返回的迭代器指向容器的超出末端的下一位置。c.erase(b,e),删除一段,返回e后面的元素,如果e本身就是末端下一个位置,则返回的也是某端下一个位置。

       c.clear();删除容器c所有元素;c.pop_back()/pop_front()删除c的最后一个/第一个元素,都返回void

       algorithm头文件中的find函数,需要一对标记查找范围的迭代器以及一个在该范围内查找的值作为参数。查找完成后,该函数返回一个迭代器,它指向具有指定值的第一个元素,或超出末端的下一个位置。

       vector容器,指向删除点后面的元素的迭代器通常会失效,对于deque,如果删除时不包括第一个元素或最后一个元素,那么所有相关迭代器都会失效。(不太懂为啥)

9.3.8、赋值与swap

       赋值操作首先删除其做操作数容器中的所有元素,然后将右操作数容器的所有元素插入到左边容器中。

       赋值和assign操作使左操作数容器的所有迭代器失效。swap操作则不会使迭代器失效。完成swap操作后,尽管被交换的元素已经存放在另一容器中,但迭代器仍然指向相同的元素。

       c.assign(b,e)重新设置c的元素(会删除c中的全部元素,因此不能调用该函数容器内的迭代器),将迭代器b和e标记的范围内所有的元素复制到c中。be必须不是指向c中元素的迭代器。它比赋值操作好在元素类型不相同,但是兼容,也可以赋值。

       s1.swap(s2);交换s1和s2中的内容,操作数必须是相同类型的容器,而且所存储的元素类型也必须相同

9.4、vector容器的自增长

       vector较list,在增加元素需要增加空间时,效果没有list好。但vector带来的访问便利弥补了其存储代价。为了使vector容器实现快速的内存分配,其实际分配的容量要比当前所需的空间多一些。

       vector的capacity指容器在必须分配新存储空间之前可以存储的元素总数。size方法指容器当前拥有的元素个数。当vecotr没有元素时,两者都为0。在VS2010中,前面添一个,capacity跟个数一样,当size为5时,capacity为6,后面capacity每次增加后的都比size的大。VS2010增加的策略是增加为当前容量的3/2倍。当前为6,当size变为7,capacity则变为6*3/2=9。

       vector的reserve(int)方法告诉vecotr容器应该预留多少个元素的存储空间。让预留空间不够时,分配多少内存取决于实现方法,不同的库采用不同的策略实现。

9.5、容器的选用

       deque支持对所有元素的随机访问,与vector相同点在中间insert或erase元素效率比较低,不同在于它在首部也可以高效插入和删除元素。在deque首部或尾部插入元素不会使任何迭代器失效,在首部和尾部删除元素则只会使被删除的元素的迭代器失效。在其他位置插入和删除则使所有迭代器都失效。

       一般都首选vector。如果真是中间插入删除占主要用list。好的实践方法,在无法确定用哪种容器,则使用vector和list都提供的操作迭代器,而不是下标,并避免随机访问元素,这样可以方便程序从vector转换为list。

9.6.1、构造string对象的其他方法

       charno_null[] = {'H','i'};//将它赋值给string s1(no_null);,由于末尾不带null,输出Hi后面的是乱码,VS2010还是可以运行的。如果是string s1(no_null, 2);则可以,输出Hi。

       char *cp= "hi";//这两个可以

       charc_array[] = "World";

       构造string对象的其他方法:(1)string s(cp, n)创建一个string对象,它被初始化为cp所指向数组的n个元素的副本,n超出size则该操作未定义;(2)string s(s2,pos2);从pos2开始,可以添加第三个参数len,用于表示从pos2开始的len个字符。

9.6.2、修改string对象的其他方法

       所有版本的insert函数的第一个参数都是一个指向插入位置之后的迭代器,而新插入的元素值则由其他参数指定。

       对于insert和assign的用法,查这C++ primer即可p292。

9.6.3、只适用于string类型的操作

       substr函数,返回当前string对象的子串。操作有:substr(pos,n),substr(pos),substr()。

       s.append(arg)(在args串接到s后面)和replace函数(可用迭代器或下标作为参数),用于修改string对象。

       当replace(s下标pos开始,len个字符,args),这边args不能是两个迭代器参数。

       当replace(迭代器b,迭代器e,args),这边args不能是s2,pos2,len2,字符串s2中从下标pos2开始的len2个字符。

       一系列find函数,用于查找string对象。

9.6.4、string类型的查找操作

       find函数返回string::size_type类型的值,以下标形式标记查找匹配所发生的位置,或者返回一个string::npos的特殊值,说明查找没有匹配(VS2010中,npos值为2^32-1)。

       find_first_of(args);find_last_of(最后一次出现的下标)/find_first_not_of这些可以用于查找args的任意字符的第一次出现/最后一次出现/第一个不属于args的字符。而find/rfind(在s中查找args最有一次出现的下标)则是精确匹配args,不再是args的任意一个字符。

9.6.5、string对象的比较

       compare函数有各种比较方法,如s.compare(pos1,n1,s2,pos2,n2)让s中从pos1下标位置开始的n1个字符与s2中从pos2下标位置开始的n2个字符作比较。

9.7、容器适配器

       适配器是标准库中通用的概念,包括容器适配器、迭代器适配器和函数适配器。

       默认的stack和queue都基于deque容器实现,而priority_queue则在vector容器上实现。stack适配器所关联的基础容器可以是任意一种顺序容器类型(可以建立在vector、list或者deque容器之上),而queue由于要求基础容器必须提供push_front运算,因此只能建立在list容器上,不能在vector上。priority_queue适配器要求提供随机访问功能,因此可以建立在vectordeque容器上,但不能建立在list容器上

       stack操作中:pop()删除栈顶元素但不返回其值;top()返回栈顶元素的值,但不删除该元素。

       队列和优先级队列支持的操作:q.front()/back()只适用于队列,返回队首或队尾元素值,不删除。q.top()只适用于优先级队列,返回具有最高优先级的元素值,但不删除该元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值