您的位置:首页 > 编程语言 > C语言/C++

学习C++——顺序容器(1)

2015-01-31 15:33 190 查看

1、顺序容器概述

以下表格列出了标准库中的顺序容器,所有的顺序容器都提供了快速顺序访问元素的能力。

顺序容器类型

vector可变大小数组。支持快速随机访问。元素是连续存储。
deque双端队列。支持快速随机访问。在头尾位置插入、删除速度很快。
list双向链表。支持双向顺序访问。在任何位置插入、删除速度都很快。
forward_list单向链表。只支持单向顺序访问。在任何位置插入、删除速度都很快。
array固定大小数组。支持快速随机访问。不能添加或删除元素。
string与vector类似的容器,但专门用于保护字符。随机访问快,在尾部插入或删除速度快。
forward_list和array是新的C++标准增加的类型。

确定使用哪种顺序容器

通常,使用vector是最好的选择,除非有很好的理由选择其他容器。

以下是一些选择容器的原则:

除非你有很好的理由选择其他容器,否则应使用vector
如果你的程序有很多小的元素,且额外开销很重要,则不要使用list和forward_list
如果程序要求随机访问元素,应使用vector或deque
如果要求在容器的中间插入或删除元素,应使用list或forward_list
如果需要在头尾位置插入或删除元素,但不会在中间位置进行插入或删除操作,则使用deque

2、容器库概述

每个容器都定义在一个头文件中,文件名和类型名相同。即,deque定义在头文件deque中,list定义在头文件list中,等等。

顺序容器几乎可以保存任意类型的元素。特殊情况下是,定义一个容器,其元素类型是另外一个容器。如:vector<vector<string>> lines;

容器操作:

类型别名
iterator此容器类型的迭代器类型
const_iterator可以读取元素,但是不能修改元素的迭代器类型
size_type无符号整数类型,保存此种容器类型最大可能容器的大小
difference_type带符号整数类型,足够保存两个迭代器之间的距离
value_type元素类型
reference元素的左值类型,与value_type & 含义相同
const_reference元素的const左值类型(即,cosnt value_type &)

迭代器运算

vector、string、deque和array迭代器支持的运算

iter+n迭代器指向的位置向前移动n个位置
iter-n迭代器指向的位置向后移动n个位置
iter += niter = iter + n
iter -= niter = iter - n
iter1- iter2
>,>=,<,<=iter1如果在iter2指向的位置之前,则iter1小于iter2

迭代器范围

[ bigen, end)
while(begin != end)
{
*begin = val;//将begin指向位置的元素值设为val
++begin;//移动迭代器,获取下一个位置
}


迭代器的类型

auto len = line.size();//len的类型是string::size_type;
vector<int>::iterator it;//it能读写vector<int>的元素。
vector<int>::const_iterator it2;//it2只能读元素,不能写元素。
方向容器的成员,reverse_iterator和const_reverse_iterator,它们和之前的那两个的++,--含义是相反的,其它含义都是一样的。

begin和end成员

list<string>a = {"ya","xi","ku"};
auto it1 = a.begin();//list<string>::iterator
auto it2 = a.rbegin();//list<string>::reverse_iterator
auto it3 = a.cbegin();//list<string>::const_iterator
auto it4 = a.crbegin();//list<string>::const_reverse_iterator


与顺序容器大小相关的构造函数

vector<int> ivec(10, -1);//10个int元素,每个值都初始化为1
list<string> svec(10, "hello");//10个string元素,每个值初始化为hello
forward_list<int> ivec(10);//10个int元素,每个都初始化为0
deque<string> svec(10);//10个string元素,每个都是空字符串

列表初始化(C++11标准)

list<string> peo = {"ya", "xi", "kui"};
vector<char *> peo = {"ya", "xi", "kui"};


标准库array具有固定的大小

与内置数组一样,标准库array的大小也是类型的一部分。当定义一个array时,除了指定元素类型,还要指定容器大小。

array<int, 42>       //这是一个数据类型,保存42个int的数组
array<string, 10>    //这是一个数据类型,保存10个string的数组
array<int, 10> ival1;//10个默认初始化的int
array<int, 10> ival2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};//列表初始化
array<int, 10> ival3 = {42};//ival[0] = 42,其余元素都是0


赋值和swap

容器赋值运算

c1 = c2将c1中的元素变为c2中元素的拷贝。c1,c2必须有相同的类型
c = {a,b,c....}将c中的元素变为初始化列表中元素的拷贝,array除外。
swap(c1, c2)交换c1和c2的元素。两个具有相同的类型。速度比从c2向c1拷贝元素快得多。
c1.swap(c2)交换c1和c2的元素。两个具有相同的类型。速度比从c2向c1拷贝元素快得多。等价于swap(c1, c2)
seq.assign(b,e)将seq中的元素替换为迭代器b和e所表示的范围中的元素。迭代器b和e不能指向seq中的元素。
seq.assign(i1)将seq中的元素替换为初始化列表i1中的元素
seq.assign(n, t)将seq中的元素替换为n个值为t的元素
备注:

assign操作不适用于关联容器和array
赋值相关运算会导致指向左边容器内部的迭代器,引用和指针失效。
swap操作将容器内容交换不会导致指向容器的迭代器,引用和指针失效。(容器类型为array和string的情况除外)

使用assign

赋值运算符要求左边和右边的运算对象具有相同的类型。但是assign允许我们从一个不同但是相容的类型赋值,或者从一个容器的一个子序列赋值。
list<string>  names;
vector<const char *> oldstyle;
names = oldstyle;//错误,容器类型不匹配
names.assign(oldstyle.cbegin(), oldstyle.cend());
//对assign的调用将names中的元素替换为迭代器指定的范围中的元素的拷贝。
第二个版本的assign,接受一个整型值和一个元素值
<span style="white-space:pre">	</span>list<string> slist(1);//1个元素,为空string
slist.assign(10, "Hiya");//10个元素,每个都是“Hiya”


使用swap

vector<string>  svec1(10);
vector<string>  svec2(24);
swap(svec1,svec2);
//调用swap后,svec1将包含24个string元素,svec2将包含10个string元素。


除了string之外,指向容器的迭代器,引用和指针在swap之后都不会失效。它们仍然指向swap之前所指向的那些元素。但是这些元素已经属于是不同的容器了。
swap两个array会真正交换它们的元素。在swap操作之后,指针、引用和迭代器所绑定的元素保持不变,但元素值已经与另一个array中对应元素的值进行了交换。

容器大小操作

成员函数size返回容器中元素的数目
empty当size为0时返回布尔值true,否则返回false。
max_size返回一个大于或等于该类型容器所能容纳的最大元素数的值。
forward_list支持max_size和empty,但是不支持size。

关系运算符

==, !=, >, >=, <, <=
关系运算符左右两边的运算对象必须是相同类型的容器,且必须保存相同类型的元素。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: