初探vector容器与迭代器

Vector容器

标准库类型vector表示对象的集合,其中所有对象的类型相同,且有一个与之对应的索引。要想使用vector,必须包含适当的头文件 #include

注意!!!

vector是模版而非类型,由vector生成的类型必须包含vector中的类型,例如:

vector<int> ivec; //ivec 保存 int 类型的对象
vector<Sales_item> Sales_vec; //保存Sales_item类型的对象
vector<vector<string>> file; //该向量的元素是vector对象

vector 能容纳绝大多数类型的对象作为其元素,但是因为引用不是对象,所以不存在包含引用的vector。
还有在早期版本的C++标准中对于上述第三条代码的用法有所不同,过去必须在外层vector对象的右尖符号和其元素类型之间添加一个空格,如应该写成:

vector<vector<string> > file;

定义和初始化vector

关于一些常用的初始化vector对象方法:
方法解释
vector< T > v1v1是一个空vector,他潜在的元素是T类型,执行默认初始化
vector< T > v2(v1)v2包含有v1所有元素的副本
vector< T > v2 = v1等价于v2(v1) , v2中包含有v1所有元素的副本
vector< T > v3(n, val)v3包含了n个重复的元素,每个元素的值都是val
vector< T > v4(n)v4包含了n个重复地执行了值初始化的对象
vecto< T > v5{a,b,c…}v5包含了初始值个数的元素,每个元素被赋予相应的初始值
vecto< T >v5={a,b,c…}等价于v5{a,b,c…}

关于它的列表初始值还是元素数量

在某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。当用== 圆括号 的时候,它的初始值代表着它的 容量 ;当为 花括号 时,它的初始值代表它的 元素的初值 ==。
当然也有特殊情况,在花括号中,如果提供的值不能用来列表初始化,就要考虑用这样的值来构造vector对象了。例如:

vector<string> v5{"h1"}; //列表初始化,v5有一个元素hi
vector<string> v5{"h1"}; //错误:不能使用字符串字面值构建vector 对象
vector<string> v7{10}; //v7有10个默认初始化的元素,
vector<string> v8{10,"hi"}; //v8有10个值为“hi”的元素

上述的例子只有第一条是列表初始化。第三条因为不能用 int 初始化string对象,所以v7和v8提供的值不能作为元素的初始值,无法执行列表初始化后,只能尝试用默认值初始化vector对象。

向vector对象中添加元素

一.运用push_back函数向其中添加元素

push_back函数负责把一个值当成vector对象的尾元素“压缩到(push)”一个vector对象的“尾端(back)”。例如:

string word;
vector<string> text; //空vector对象
while (cin>> word){
	text.push_back(word);
}		//把word添加到text后面
二.使用下标形式添加元素

它也能和数组一样使用下标来访问容器里的数据,但是前提是在定义容器时,需要初始化容器的容量,否则会报错,例如:

string word;
vector<string> text(10);
for(int i=0;i<10;i++)
{
	cin>>word;
	text[i] = word;
}

关于访问vector中的元素

访问vector的元素方法和字符串一样,也是通过字符串元素在vector对象中的位置,例如:

vector (auto &i : v)	//这里运用引用是为了能改变vector对像中元素的值
	i*= i;
for (auto i :v)		//这里是单纯访问v中的每个元素,并不对里面的元素做修改。
	cout<<i<<" "; 
cout<<endl;

迭代器

我们已知的除了可以用下标运算符来访问string对象的字符或vector对象的元素,还有就是迭代器。所有标准库容器都可以使用迭代器,但是其中只有少数几种才能同时使用下标和迭代器,所以我们还需要掌握迭代器。
关于迭代器的具体类型,我们不需要了解清楚,就像不知道string和vector中的size_type成员一样,在运用的时候统一用auto来获取迭代器的类型,例如:

auto a=v.begin(), b=v.end();	//a代表v中的第一个元素,b代表v中的第二个类型,a与b都是相同类型

在拥有迭代器的标准库类型使用iteratorconst_iterator 来表示迭代器的类型(前者是可读写,后者是只可读,跟const一样)

vector<int>::iterator it;	//it能读写vector<int>的元素
string::iterator it2;	//it2能读写string的元素
vector<int>::const_iterator it3;	//it3只能读vector<int>的元素,不能写元素
string::iterator it4;	//it4同样只能读元素,而不能写元素

迭代器运算符操作

迭代器的解引用和成员访问操作

迭代器的解引用理解和指针差不多,对他解引用就是访问所指对象的值,例如判断一个迭代器所指的字符串是否为空:

(*it).empty()	//解引用it,然后调用结果对象的empty函数,判断是否为空
*it.empty();	//错误,试图访问it的名为empty的成员,但it是个迭代器,没有empty成员

所以从上述代码中,我们还需要注意*的运算顺序,记得要加括号!

除了解引用,C++还定义了箭头运算符(->).意思是把解引用和成员访问两个操作两个结合在一起,也就是说 it->mem和(*it).mem表达的意思是一样的。
例如:假如用一个名为text的字符串向量存放文本文件的数据,其中的元素或者是一句话或者是一个用于表示段落分隔的空字符串。如果要输出text中第一段的内容,可以利用迭代器写一个循环令其遍历text,直到遇到空字符串为止:

//依次输出的text的每一行直至遇到第一个空白行为止
for(auto it=next.cbgein(); it !=text.cend()&&!it->empty();++it)
cout<< *it<<endl;

注意,vector对象虽然可以动态地增长,但是也会有一些副作用,已知的一个限制是不能在范围for循环中向vector对象添加元素。另一个限制是任何一种可能改变vector对象容量的操作,比如push_back,都会使该vector对象的迭代器失效。

加减运算与逻辑运算

和下标运算差不多, 一个迭代器加n:表示向后移n个元素;

减n则代表向前移n个元素;

iter1+=n:则代表将iter1 加n的结果赋给iter1;

两个迭代器相减,则代表两个迭代器的距离,类型是difference_type,一种带符号的整型数;

“>、>=、<、<=”:如果迭代器所指的容器位置在另一个位置之前,则说明前者小于后者,后面的以此类推。

begin运算符和end运算符

一些有迭代器类型的容器同时拥有返回迭代器的成员。
比如begin和end的成员时,

begin成员就是负责返回指向第一个元素或(第一个字符)的迭代器。

end成员返回的迭代器通常被称作“尾后迭代器”或者简称尾迭代器 ,即返回尾元素的下一个位置的迭代器,也就是说该迭代器指示的是容器一个本不存在的“尾后”元素。这样的迭代器其实没什么实际含义,仅是个标记,表示我们处理完了容器中的所有元素。

当容器为空的时候他们返回的是同一个迭代器。

因为迭代器有const类型的,所以我们还拥有cbegin和cend来专门得到const_iterator类型的返回值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值