容器
标准库的vector类型。
vector是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。它将负责和管理与存储元素相关的内存。我们将vector称为容器。一个容器的所有对象必须是同一种类型的。
vector是一个类模板。使用模板可以编写一个类定义或者函数定义,用于多个不同的数据类型。它一个线性顺序结构的容器。相当于数组,但是其大小可以不预先指定,并且自动扩展,它可以像数组一样操作,但是由于它的特性我们可以将他看做动态数组。
声明从类模板产生的某种类型的对象,必须在后面的尖括号中说明对象的类型。
vector<int> ivec; //需要定义类型和一个变量的列表
vector<int>含有若干个int类型对象的vector.变量名为ievc;
vector不是一种数据类型,是一个类模板,可以用来定义任意多种的数据类型。每一种都指定了元素的类型值,因此vector<int>和vector<string>都是数据类型。
初始化vector的方式:
vector<T> v1; 保存类型为T的对象,默认的构造函数v1为空
vector<T> v2(v1); v2是v1的一个副本
vector<T> v3(n,i); 包含n个值为i 的元素
vector<T> v4(n); v4含有初始化为i的n个副本
vector<T> v5(v3.begin(),v3.begin()+3); v3向量中第0个到第2个
也可以用数组初始化向量vector
int a[7] = {1,2,5,3,7,9,8};
vector<int> va(a,a+7);
关键的概念:vector对象动态增长
vector对象(以及其他的标准库容器对象)的重要属性就是可以在运行时高效的添加元素。因为vector的增长效率高,所以在元素值已知的情况下,最好是动态的添加元素。
虽然可以给定元素个数的vector对象预先分配内存,但是初始化一个空的vector对象,然后再动态的添加是一个更有效的方法。
2.初始化
如果没有指定元素的初始化值,标准库将自行提供一个元素的初值来初始化。
vector<int> f(10); //10个元素初始化为0
vector<string> str(10); //10个元素初始化为空string
3.vector的对象操作
vector的标准库提供了愈多类似于string对象的操作。几个重要的vector的操作:
v.empty() //判断Vector是否为空(返回true时为空)
v.size() //元素个数
v.push_back(t) //在末尾增加一个值为t的元素
v.pop_back() 移除最后一个元素
v[n] //返回位置为n的元素v1 = v2 //将v1中的所有元素替换为v2副本
v1 == v2 //判断是否相等
!=,<,<=,>,>= 保持原来的含义
v.clear() 清空所有元素
v.back() 返回最末一个元素
v.erase() 删除指定元素
语法:
iterator erase( iterator loc );//删除loc处的元素
iterator erase( iterator start, iterator end );//删除start和end之间的元素
v.front() 返回第一个元素的引用
v.get_allocator() 返回vector的内存分配器
v.insert() 插入元素到Vector中
语法:
iterator insert( iterator loc, const TYPE &val );
//在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器,
void insert( iterator loc, size_type num, const TYPE &val );
//在指定位置loc前插入num个值为val的元素
void insert( iterator loc, input_iterator start, input_iterator end );
//在指定位置loc前插入区间[start, end)的所有元素
v.max_size() 返回Vector所能容纳元素的最大数量(上限)
v.rbegin() 返回Vector尾部的逆迭代器
v.rend() 返回Vector起始的逆迭代器
v.reserve() 设置Vector最小的元素容纳数量
//为当前vector预留至少共容纳size个元素的空间
v.resize() 改变Vector元素数量的大小
vector对象操作:
vector的下标操作:
vector的对象没有命名,可以按vector中对象的位置来访问他们。 使用下标操作符来获取元素。
vector的下标操作符接受一个值,并返回vector中该对应位置的元素。vector的位置从0开始。
但是下标操作不会添加元素,要是空的vector对象。 下标只能用于获取已经存在的元素。
只能对已经存在的元素进行下标的操作,获取不存在的元素必然会导致运行的错误。
4.使用迭代器来访问vector对象的元素
除了使用下标访问vector以外,用迭代器也可以访问(标准库)的方法。迭代器是一种检查容器内部元素并遍历元素的数据类型。
标准库为每一个标准容器定义了一种迭代器类型。迭代器提供了比下标更加通用化的一些方法,:所有的都适用。
表中库容器都有相应的迭代器类型,它对所有的容器都适用。
容器的iterator类型:
vector<int>::iterator iter;
这个变量是由vector<int>定义的iterator类型。
各容器都定义了自己的iterator类型,用于访问容器间的元素,每个容器都定义了一个名为iterator的类型,这种类型支持迭代器的各种操作。
begin和end操作:
没种容器都定义了命名为begin和end的函数,用于返回迭代器。如果容器有元素的话,由begin返回的是迭代器的指向的第一个元素:
vector<int>::iterator iter = ivec.begin();
初始化后iter指向的ivec[0].
由end返回的是迭代器vector指向的“末端元素的下一个”,表明了它指向的是一个不存在的元素。如果vector为空,则begin返回的迭代器和end返回的迭代器相同。
由end返回的迭代器并不会指向vector中的实际元素,它只是起到一个哨兵sentinel的作用,表示我们已经处理完vector中的所有元素。
vector迭代器的自增和解引用运算
迭代器类型可以使用解引用的操作(*)来访问迭代器所指向的元素:
*iter = 0;
实际上是将这个元素赋值为0。
迭代器的自增操作实际上是将迭代器向前移动一个位置。 如果iter指向的是第一个元素,则++iter指向的是第二个元素。
注意:end不指向任何的元素,所以不能对end执行解引用或者用自增操作。
迭代器可以用==或者!=来比较,如果两个迭代器指向同一个元素,则他们相等,否则就不相等。
用法:
用迭代器来编写循环
vector<int> ivec(10);
for(vector<int>::iterator iter = ivec.begin();iter != ivec.end();++iter)
*iter = 0;
解引用操作符返回的是一个左值,因此可以赋值来改变它的值,上述的循环就是将ivec中的所有元素都赋值为0;
如果vector为空,则程序使安全的,因为ivec为空,所以begin返回的迭代器不指向任何的元素。所以begin和end返回的迭代器的值相同,for语句的测试条件立即失败。
const_iterator
前面的迭代器vector::iterator改变vector的元素值。 每种容器类型还定义了const_iterator的类型,该类型只能用于读取容器内的元素,但是不能改变其值。
for(vector<string>::const_iterator iter = text.begin();iter != text.end();++iter)
cout<<*iter<<endl;
但是不能借助迭代器进行写操作,比如这样:*iter = " ";是不允许的。
《C++ primer》//笔记