【C++】 vector和迭代器

C++ vector/迭代器

一、vector

1、定义

标准库类型vector表示对象的集合,其中所有对象的类型都相同,集合中的每个对象都有一个与之对应的索引,索引用于访问对象。vector“容纳着"其他对象,所以也被称作容器。

使用vector的方法:

#include <vector>
using std::vector;

本质上vector是一个类模板,模板本身不是一个类或函数,相反可以将模板看作为编译器生成类或者函数编写的一份说明书。编译器根据模板创建类或函数的过程称作为实例化。

vector能容纳绝大多数类型的对象作为其元素,但是引用不是元素,所以不包含引用的vector。组成vector的元素也可以是vector,类似二维数组。

2、vector的初始化

img

2.1、默认初始化

默认初始化为0,默认初始化为空字符串。

默认初始化vector对象,从而创建一个指定类型的空vector。

2.2、列表初始化
vector<string> data{"hello","world","!!!"};
vector<vector<string>> ve_data(3,data);

data对象包含三个元素,第一个是“hello”、第二个是“world”、第三个是“!!!”

ve_data对象是以三个data对象作为自身元素,类似于二维数组

ve_data[0][0]="hello";
ve_data[0][1]="world";
ve_data[0][2]="!!!";
...
ve_data[2][0]="hello";
ve_data[2][1]="world";
ve_data[2][2]="!!!";

初始化的三个点:

  • 使用拷贝初始化时,只能提供一个初始值;
  • 如果提供的是一个类内初始值,则只能使用拷贝初始化或者使用花括号的形式初始化;
  • 如果提供的是初始元素值的列表,则只能把初始值都放在花括号里进行列表初始化。
vector<string> v2{"a","an","the"};//列表初始化
vector<string> v2("a","an","the");//错误

2.3、创建指定数量的元素

vector<int> ivec(10,-1);//10个int类型的元素,每个元素初始化为-1
vector<string> svec(10,"hi");//10个string类型的元素,每个被初始化为“hi”

只提供vector对象容纳的元素数量而省略初始值,此时库会自动创建一个值初始化的元素初值,并赋给容器中的所有元素,这个值有vector对象的元素类型决定。

vector<int> idata(10);//idata有10个默认初始化的int类型的元素
vector<string> sdata(10);//10个元素,每个都是空的string对象

这种初始化的方式有两个特殊限制:

  • 有些类要求必须明确地提供初始值,不提供初始值无法完成初始化工作;
  • 如果只提供了元素的数量而没有设定初始值,只能使用直接初始化

2.4、列表初始值还是元素数量

初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。

vector<int> v1(10);//v1有10个元素,每个都是0
vector<int> v2{10};//v2有1个元素,该元素的值是10

vector<int> v3(10,1);//v3有10个元素,每个的值都是1
vector<int> v4{10,1};//v4有两个元素,分别是10和1

如果使用的是圆括号,可以说提供的值是用来构造vector对象的。

如果使用的是花括号,可以表述我们想列表初始化该vector对象。

vector<string> v5{10,"hi"};//v5有10个值为“hi”的元素

使用花括号列表初始化vector对象时,花括号里的值必须与元素类型相同,不然就会转变为构造vector对象。

3、vector的操作

3.1、向vector中添加元素

使用vector的成员函数push_back向vector对象中添加元素。push_back负责把一个值档成vector对象的尾元素”压到(push)“vector对象的”尾端(back)“。

vector<unsigned int> cin_data;
for (unsigned int i = 0; i < 10; ++i)
{
    cin >> cin_data;
    data.push_back(cin_data);
}

不能在范围for循环中向vector对象添加元素,任何一种可能改变vector对象容量的操作都会使该vector的迭代器失效。

vector的其他操作

请添加图片描述

vector要使用size_type时,要首先制定它是由那种类型定义的。vector对象的类型总是包含着元素的类型。

vector<int>::size_type  //正确
vector::size_type 		//错误

vector可以使用下标索引访问元素,但不能使用下标形式添加元素。

vector也可以使用迭代器访问。

二、迭代器

1、定义

迭代器(iterator)是一种可以遍历容器元素的数据类型。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。类似于指针类型,迭代器也提供了对对象的间接访问。C++更趋向于使用迭代器而不是数组下标操作,因为标准库为每一种标准容器(如vector、map和list等)定义了一种迭代器类型,而只有少数容器(如vector、string)支持数组下标操作访问容器元素。

b表示v的第一个元素,e表示v尾元素的下一个位置。该迭代器指示的是容器一个本不存在的“尾后”元素,这样的迭代器本身没有什么意义,仅是个标记而已,end成员返回的迭代器常被称作尾后迭代器

vector<int> v(10,2);
auto beg=v.begin(),e=v.end();	//b表示v的第一个元素,e表示v尾元素的下一个位置

如果容器为空,begin和end返回的是同一个迭代器,都是尾后迭代器。

2、迭代器运算符

在这里插入图片描述

尾后迭代器并不实际指示某个元素,所以不能对其进行增减或解引用操作。

3、迭代器类型

拥有迭代器的标准库类型使用iterator和const_iterator来表述迭代器的类型。

vector<int>::iterator if;	//it能读写vector<int>的元素
string::iterator it2;		//it2能读写string对象中的字符

vector<int>::const_iterator it3;//it3只能读元素,不能写元素
string::const_iterator it4;		//it4只能读字符,不能写字符

begin和end函数返回iterator类型,而cbegin和cend返回const_iterator类型。

4、结合解引用和成员访问操作

解引用迭代器可以获得迭代器所指的对象,如果该对象是类,就可能希望进一步访问它的成员。

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

(*it).empty()中的圆括号必不可少,先对it进行解引用,然后再执行点操作符。

*C++语言定义了箭头运算符(->),箭头运算符把解引用和成员访问两个操作结合在一起,也就是说(it).empty()和it->empty()意思相同。

5、迭代器运算

迭代器的递增运算令迭代器每次移动一个元素,所有标准库容器都有支持递增运算的迭代器,也可以使用!=,==对任意标准库类型的两个有效迭代器进行比较。
在这里插入图片描述

例子:二分搜索法

//text必须是有序的
//beg和end表示我们的搜索范围
auto beg = text.begin();
auto end = text.end();
auto mid = text.begin() + (end - begin)/2;

while (mid != end && *mid != sought)
{
	if (sought < *mid)				//要找的元素在前半部分
		end = mid;					//在前半部分寻找
	else							//要找的元素在后半部分
		beg = mid + 1;				//在mid之后查找
	mid = beg + (end - beg)/2;		//新的中间点
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值