C++Primer读书笔记(第九章)

第九章顺序容器

9.1 顺序容器的定义

         顺序容器包括:vector、list和deque(双端队列),顺序适配器包括:stack、queue和priority_queue。

         使用容器时,必须先包含相应的头文件:

         #include             #include          #include

         vector  svec;     list  ilist;                   deque  items;

         所有容器类型都定义了默认构造函数,用于创建指定类型的空容器对象,大多数程序中,默认构造函数运行性能最佳。

9.1.1 容器元素的初始化

         C  c;          //创建名为c的空容器,C是容器类型名,T是元素类型

         C  c (c2);                   //创建容器c2的副本c

         C  c (b, e);       //c是迭代器b和e标示范围内的元素副本,b和e是其它容器的迭代器

         C  c (n, t);       //用n个值为t的元素创建初始化容器c

         C  c (n);           //创建n个值初始化元素的容器c

         后两者指定容器元素个数,只适用于顺序容器,不适用于关联容器。

9.1.2 容器内元素的类型约束

         容器元素类型必须满足以下两个约束:

         (1)元素类型必须支持赋值运算;

         (2)元素类型的对象必须可以复制。

         对于元素是类类型的容器,还得注意构造函数对不同初始化方法的支持。对于容器的容器,必须用空格隔开两个相邻的>符号。

         vector< vector >         lines;         //ok

         vector> lines;                //error

9.2 迭代器和迭代器范围

9.2.1 迭代器基本操作

迭代器为所有标准库容器类型提供的运算如下:

*iter                   iter->mem        ++iter       iter++       --iter         iter--         iter1 == iter2   iter1 != iter2

vector和deque容器的迭代器提供了额外的运算,因为只有它们支持通过元素位置直接有效访问指定元素。

iter + n     iter – n               iter1+= iter2            iter1 -= iter2             iter1 – iter2      >, >=, <, <=

9.2.2 迭代器范围

         左闭合区间:[first, last ),last指向的是最后一个元素的下一个位置。

         使用迭代器时,必须留意哪些操作会添加或删除元素,使得迭代器失效。

9.3 顺序容器的操作

9.3.1 容器定义的类型别名

size_type

无符号整型,足以存储此容器类型的最大长度

iterator

迭代器类型

const_iterator

元素只读迭代器类型

reverse_iterator

按逆序寻址元素的迭代器

const_ reverse_iterator

元素只读逆序迭代器类型

different_type

有符号整型,存储两个迭代器差值

value_type

元素类型

reference

元素的左值类型,同value_type &

const_ reference

同const  value_type &

9.3.2 begin和end成员

c.begin()

返回一个迭代器,指向容器c的第一个元素

c.end()

返回一个迭代器,指向容器c的最后一个元素的下一位置

c.rbegin()

返回一个逆序迭代器,指向容器c的最后一个元素

c.rend()

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

         上述操作都有一个const版本,如果容器c是const类型,那么它们返回的迭代器类型也是const类型。

9.3.3 在顺序容器中添加元素

c.push_back(t)

在容器c末尾添加值为t的元素,返回void类型

c.push_front(t)

在容器c前端添加值为t的元素,返回void类型,只适用于list和deque

c.insert(p, t)

在迭代器p所指元素前插入t,返回指向新添加元素的迭代器

c.insert(p, n, t)

在迭代器p所指元素前插入n个t,返回void类型

c.insert(p, b, e)

在迭代器p所指元素前插入由迭代器b和e标记范围内的元素,返回void

         当编写循环将元素插入到容器中时,程序必须确保迭代器在每次循环后都得到更新。对于end操作返回的迭代器,每次添加或删除元素都会导致存储的迭代器失效。建议不要存储end操作返回的迭代器。

9.3.4 关系操作符

         C++语言只允许两个容器做其元素类型定义的关系运算,若两个容器是vector类型,则使用string类型的关系运算,若为vector类型,则不允许关系运算。容器类型的关系比较类似于string类型的关系运算。

9.3.5 容器大小的操作

c.size()

返回容器c的元素个数,返回类型为c::size_type

c.max_size()

返回容器c可容纳的最多元素个数,返回类型为c::size_type

c.empty()

容器大小是否为0的布尔值

c.resize(n)

调整c的长度为n。如果n< c.size(),则删除多余元素,否则添加初始化元素

c.resize(n, t)

调整c的长度为n。若添加新元素,初始化为t

9.3.6 访问元素

c.back()

返回c的最后一个元素的引用,若c为空,则该操作未定义

c.front

返回c的第一个元素的引用,若c为空,则该操作未定义

c[n]

返回下标为n的元素的引用,只适用于vector和deque

c.at(n)

返回下标为n的元素的引用,只适用于vector和deque

         c.at(n)比c[n]更安全,如果下标越界,会抛出out_of_range异常。

9.3.7 删除元素

c.erase(p)

删除迭代器p所指向的元素,返回一个指向被删元素后面元素的迭代器。如果p本身指向末端的下一位置,则该函数未定义

c.erase(b, e)

删除迭代器b和e范围内的所有元素,但会指向被删元素后面元素的迭代器。如果e本身指向末端的下一位置,则返回迭代器也指向末端的下一位置。

c.clear()

删除所有元素,返回void

c.pop_back()

删除最后一个元素,返回void。若c为空,则该函数未定义

c.pop_front()

删除第一个元素,返回void。若c为空,则该函数未定义,只适用于list和deque

9.3.8 赋值与swap

c1=c2

删除c1的所有元素,然后将c2的元素复制给c1,c1和c2类型必须相同

c1.swap(c2)

交换内容,此操作速度较快,c1和c2类型必须相同,迭代器不会失效

c.assign(b, e)

将迭代器b和e范围内的内容复制到c中,b和e必须不是c的迭代器

c.assign(n, t)

将c重新设置为存储n个值为t的元素

       assign操作首先删除容器中原有所有元素,因此,迭代器b和e不能指向原容器。带有一对迭代器参数的assign操作允许我们将一个容器的元素赋值给不同类型的容器。

9.4 vector容器的自增长

         vector中元素时顺序存储的,vector容器处理内存分配时,有两个成员函数:capacity和reserve。capacity操作获取容器当前分配的存储空间最多能够存储元素的总个数,reverse操作告诉vector容器应该预留多少个存储空间。

         size()获得的是容器中目前有多少个元素,加上预留的容量才是capacity()获得的总数,reverse(n)设定capacity()的总数。

         当size和capacity相等时,再插入元素,容器将原存储的元素复制到新的存储空间,并且删除原存储,再插入新的元素。

9.5 容器的选用

         vector和deque都支持随机访问,deque相比于vector提供了高效地首部插入、删除操作。若要中间插入,则用list容器最好。

9.6 再谈string类型

         可以把string类型看作顺序容器,但是不支持以栈方式操作容器:不能使用front、back和pop_back操作。

         string类型特有的操作如下。

9.6.1 构造string对象的其它方法

string  s (cp, n)

初始化为cp所指向数组的前n个元素的副本

string  s (s2, pos2)

s2对象中从下标pos2开始的字符副本

string  s (s2, pos2, len2)

s2对象中从下标pos2开始长度为len2的字符副本

9.6.2 修改string对象的其它方法

         与容器共有的insert、assign和erase操作之外,还有:

s.insert(pos, n, c)

在下标为pos的元素之前插入n个字符c

s.insert(pos, s2)

在下标为pos的元素之前插入s2

s.insert(pos, s2, pos2, len)

在下标为pos的元素之前插入s2中从pos2开始的len个字符

s.insert(pos, cp, len)

在下标为pos的元素之前插入cp所指向数组的前len个字符

s.insert(pos, cp)

在下标为pos的元素之前插入cp所指向的字符串副本

s.assign(s2)

用s2替换s

s. assign (s2, pos2, len)

用s2中从pos2开始的len个字符替换s

s. assign(cp, len)

用cp所指向数组的前len个字符替换s

s. assign(cp)

用cp所指向的字符串副本替换s

s. erase(pos, len)

删除从pos开始的len个字符

9.6.3 只适用于string类型的操作

s.substr(pos, n)

从pos开始的n个字符的子串

s.substr(pos)

从pos开始到s末尾的子串

s.substr()

返回s的副本

s.append(args)

将args串接在s后面,返回s的引用

s.replace(pos, len, args)

删除s中pos开始的len个字符,用args指定的字符替换

s.replace(b, e, args)

删除迭代器b和e范围内的元素,用args指定的字符替换

args

s2;  s2,pos2,len2;  cp;  cp,len2;  n,c;  b2,e2;

9.6.4 string类型的查找操作

s.find(args)

在s中查找args的第一次出现

s.rfind(args)

在s中查找args的最后一次出现

s.find_first_of(args)

在s中查找args的任意字符的第一次出现

s.find_last_of(args)

在s中查找args的任意字符的最后一次出现

s.find_first_not_of(args)

在s中查找第一个不属于args的字符

s.find_last_not_of(args)

在s中查找最后一个不属于args的字符

args

c,pos;  s2,pos;  cp,pos;  cp,pos,n;

9.6.5 string对象的比较

s.compare(s2)

比较s和s2

s.compare(pos1, n1, s2)

让s中从pos开始的n1个字符与s2做比较

s.compare(pos1, n1, s2, pos2, n2)

s中从pos1开始的n1个字符与s2中从pos2开始的n2个字符做比较

s.compare(cp)

比较s和cp所指向的以空字符结尾的字符串

s.compare(pos1, n1, cp)

s中从pos1开始的n1个字符与cp

s.compare(pos1, n1, cp, n2)

s中从pos1开始的n1个字符与cp的前n2个字符

9.7 容器适配器

         使用适配器时,必须包含头文件:

         #include               #include

9.7.1 适配器基本概念

本质上,适配器是使一事物的词能够为类似于另一事物的行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。适配器包括容器适配器、迭代器适配器和函数适配器,有三种顺序容器适配器:queue、priority_queue和stack。

         适配器初始化:

         stack  atk(deq);     //deq是deque类型的容器,用deq初始化一个新的栈

         默认的stack和queue都基于deque容器实现,而priority_queue则在vector容器上实现。在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型实参,可以覆盖其默认关联的基础容器类型:

         stack > str_stk (svec);

         stack适配器所关联的基础容器可以是任意一种。queue所关联的容器必须能提供push_front运算,因此不能关联vector。priority_queue要求提供随机访问功能,因此不能关联list。

         两个相同类型的适配器可以做等于、不等、大于、小于等关系比较,只要基础元素类型支持。

9.7.2 栈适配器

s.empty()

如果栈为空,则返回true,都在为false

s.size()

返回栈中元素的个数

s.pop()

删除栈顶元素,但不返回其值

s.top()

返回栈顶元素的值,但不删除该元素

s.push(item)

在栈顶压入新元素

9.7.3 队列和优先队列适配器

q.empty()

队列为空,则为true

q.size()

返回队列中元素的个数

q.pop()

删除队首元素,但不返回其值

q.front()

返回队首元素的值,但不删除,只适用于队列

q.back()

返回队尾元素的值,但不删除,只适用于队列

q.top()

返回具有最高优先级的元素值,但不删除,只适用于优先级队列

q.push(item)

对于queue,在队尾压入一个新元素

对于priority_queue,在基于优先级的适当位置插入新元素

         使用优先级队列的程序示例是操作系统的调度表。

你可能感兴趣的:(C/C++)