2.2 容器vector
vector表示对象的合集,其中所有对象的类型都相同。
vector必须包含的头文件有:
#include <vector>
using std::vector;
需要通过提供一些信息来指定模版到底实例化成什么样的类,需要提供哪些信息由模版决定。
vector<元素类型> 容器名;
//注意元素类型不可以为引用类型,因为引用不是对象!
vector可以使用下面的一些方式来初始化
vector<T> v1; //v1为一个空vector,执行默认初始化
//括号中的值为vector类型
vector<T> v2(v1); //v2中包含有v1所有元素的副本(非复制初始化)
vector<T> v2=v1; //复制初始化
//括号中的值或为n和元素类型
vector<T> v3(n,val); //包含n个val
vector<T> v4(n); //包含了n个重复执行了值初始化(默认初始化)的元素
//列表初始化的数量可以为0,如{}
vector<T> v5{a,b,c...} //列表初始化,每个元素都被赋予相应的值
vector<T> v6={a,b,c..} //复制初始化版本的列表初始化
/*有些情况下可以使用{}来代替(),但是必须是不会造成歧义的
如:
int 元素类型就不可以,但是
vector<string> v{10,"hi"}; //可行
*/
vector<T> v7(begin(A),end(A));
//其中A为数组,begin函数指向第一个元素,end函数指向尾后元素
vector 中的一些其他操作如下
v.empty(); //判断为空则返回true,否则返回false
v.size(); //返回其大小
//注意采用下标方式是无法添加元素的,只能访问或者修改
//在使用范围for( i:n )方式的时候不可以添加元素,因为这种方式是在末尾添加哨兵的方式实现的
v.push_back(t); //将t添加到v的尾部
v[n]; //返回v中第n个位置的引用,注意从0开始计数
v1=v2; //将v2中的元素拷贝替换到v1
v1={a,b,c...} //用列表中的元素拷贝复制替换到v1中,注意列表可以为空
v1==v2 //判断它们的元素数量相同并且各对应位置的元素相等
v1!=v2
< <= > >= //以字典顺序进行比较
//最优先比较元素的值,次优先比较元素数量
2.3 迭代器
迭代器也提供了对对象的间接访问,类似于指针类型。其对象是容器中的元素或者string对象中的字符。
auto b=v.begin();
//返回指向第一个元素的迭代器
auto e=v.end();
//返回指向尾元素的下一个位置,即尾后迭代器
//如果容器为空,则begin和end返回的是同一个迭代器
标准容器迭代器的运算符
*iter //返回迭代器iter所指元素的引用
iter->mem //类似于指针的相关操作
++
--
==
!=
迭代器的精准类型不清楚,所以一般使用auto类型来定义
迭代器的两个副作用:
(1)不可以在范围for循环中添加元素
(2)任何一种可能改变vector对象容量的操作,都有可能使得迭代器失效
所以,任何一个使用了 迭代器的循环体里面,都不要向迭代器所属的容器添加元素
//迭代器的操作非常类似于数组,几乎一模一样
//注意,不可以使用两迭代器想加的操作,指针不能相加,因为很可能会溢出!
2.4 多维数组
需要注意的是auto类型,auto类型会将数组类型默认识别为指针,所以使用多维数组的时候,使用范围for语句处理多维数组,除了最内层的循环之外,其他所有循环的控制变量都应该是引用类型。
//需要修改则全部加引用
for( auto &row : A )
for( auto &x : row )
x=1;
//只需要访问不需要修改
for( auto &row : A )
for( auto x : row )
cout<<x<<endl;