《c++ primer》——2 标准库vector类型和迭代器iterator

1.标准库vector类型

vector是同一种类型的对象的集合,每个对象都对应一个相应的索引值,同string对象一样,标准库将负责管理与存储元素有关的内存

vector称之为容器。

使用vector前,包含相应的头文件

#include <vector>
using std::vector;

vector是一个类模板,因此可以定义string对象的vectorint对象的vector,或者是自定义类类型的vector

vector<int>  ivec;
vector<Sale_type> svec;
注意: vector 不是一种数据类型,只是一种类模板, vector<int> 是一种数据类型。

vector对象的定义和初始化

1.创建确定个数的元素

vector<int> ivec1;
vector<int> ivec2(ivec1);
vector<string> svec(ivec);
vector<int> ivec4(10,-1);
vector<string> svec2(10,”hi!”)
注意:vector对象的重要属性是可以在运行时动态的添加元素。因为vector增长的效率高,在元素已知的情况下,最好是动态的添加元素,而不是预先分配好合适的存储空间。

2.值初始化

 如果没有指定元素的初始化式,那么标准库将自行提供一个元素初始值进行值初始化,初始化vector中的每一个对象。初始化的结果,取决于vector中每个对象的数据类型。

 vector<int> fvec(10);//10elements,each initialized to 0
如果 vector 保存的对象为内置类型,那么标准库将用 0 初始化。 Char 类型初始化为空字符

vector<string> svec(10);
如果 vector 保存的是含有构造函数的类类型的对象,标准库将用该类类型的默认构造函数进行初始化。

还有一种情况,vector保存的是没有定义任何构造函数的类类型,这时,标准库仍产生一个带初始值的对象。

如果vector保存的是一些有自定义构造函数但没有默认构造函数的类的对象时,不能只提供创建的对象的元素的个数,还要提供元素的初始化值。

vector对象的操作

1.vector对象的size

 empty size操作类似于string类型的相关操作,size成员函数返回vector定义的size_type类型的值。

vector<int>::size_type;  //ok
vector ::size_type;    //error

int main()
{
	vector<int> ivec(10);
	cout << ivec.size()<<endl;
	if (ivec.empty())
	{
		cout << "empty" << endl;
	}
	else
	{
		cout << "not empty" << endl;
	}
	getchar();
	return 0;
}

2.向 vector 中添加元素

上面提过,在vector使用时,如果vector定义的对象的数目已经确定,也尽量不要直接分配好适当的存储空间,而是在运行时动态的分配空间,当然此时就要用到push_back成员函数。Push(元素)vectorback

3.vector的下标操作

类似于string对象的下标操作

下标的类型为vector定义的size_type类型

遍历输出:

int main()
{
	vector<string> svec;
	string s;
	while (cin >> s)
	{
		svec.push_back(s);
	}
	for (vector<string>::size_type index = 0; index != svec.size(); ++index)
	{
		cout << svec[index] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}
Vector 下标操作的对象作为左值赋值:

int main()
{
	vector<string> svec;
	string s;
	while (cin >> s)
	{
		svec.push_back(s);
	}
	for (vector<string>::size_type index = 0; index != svec.size(); ++index)
	{
		cout << svec[index] << " ";
	}
	cout << endl;
	for (vector<string>::size_type index = 0; index != svec.size(); ++index)
	{
		svec[index] = "hello";
	}
	for (vector<string>::size_type index = 0; index != svec.size(); ++index)
	{
		cout << svec[index] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}
关键概念 :良好的 c++ 编程风格

1.c++程序员习惯于优先选用!=而不是<来编写循环判断条件。

2.上述程序,并没有在循环判断条件前保存size()的返回值,而是在循环条件中调用size()函数,这是因为vector是可以动态变化的数据结构,在程序运行过程中size()的返回值可能会发生变化,如果判断条件用的是以前size()返回值,那么就会产生错误。所以更倾向于在每次循环中测试size的当前值,而不是存储size返回值的副本。  

4.下标操作不添加元素

必须是已存在的元素才能用下标操作符进行索引

int main()
{
	vector<int> ivec;
	ivec[0] = 10;//error
	ivec.push_back(10);//ok
}

2.迭代器简介

除了使用下标访问vector容器中的对象,标准库还提供了另一种访问元素的办法:使用迭代器。迭代器是一种检查容器内元素并遍历元素的数据类型

标准库为每一种标准容器都定义了一种迭代器,因此对于容器内元素的访问,迭代器要比下标操作更为普遍,因为并不是每种标准容器都支持下标访问,而每种标准容器都支持迭代器访问。

注意c++除了标准容器还有非标准容器

1.容器的iterator类型

 标准库为每种标准容器都定义了一种迭代器类型:

vector<string>::iterator iter;
2.begin end 操作

 begin返回的迭代器指向容器中的第一个元素,end返回的迭代器指向末端元素的下一个,它指向了一个容器中不存在的元素。若容器为空,则beginend返回的迭代器相同。

3.vector迭代器的自增和解引用运算

  迭代器自增来指向容器中下一个位置的对象,解引用运算来访问迭代器指向的对象的内容

  由于end操作返回的迭代器不指向任何元素,因此不能对end返回的迭代器进行解引用或自增操作。

4.迭代器的比较操作

  ==  != 用来判断迭代器是否指向同一个位置的元素

5.实例

int main()
{
	vector<int> ivec(10,1);
	for (vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
	{
		cout << *iter << " ";//解引用运算符
	}
	cout << endl;
	for (vector<int>::iterator iter = ivec.begin(); iter!= ivec.end(); ++iter)
	{
		*iter = 0;
		cout << *iter << " ";
	}
	cout << endl;
	system("pause");
	return 0;

}
6.Const_iterator

  Const_iterator指的是解引用后得到的是一个const引用的对象,也就是说不能修改其值,但const_iterator是可以变化的:迭代器指向的位置可以发生变化,但迭代器指向的位置的值不能够发生变化

  Constvector容器的iterator,这时的iterator是一个const类型,也就是说iterator指向的位置不能够发生变化,但其指向的位置的值是可以发生变化的,并且iterator在定义是就需要初始化,并且初始化后不能够再变化。

 

int main()
{
	vector<int> ivec(10,1);
	for (vector<int>::const_iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
	{
		*iter = 0;//error
	}
	for (const vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)//++iter error
	{
		*iter = 0;
	}
	return 0;
}

迭代器的算术操作:

Iterator+n

Iterator-n

返回从当前iterator指向的位置向前或向后移动n个位置的iterator,加或减之后指向的元素必须在vector容器中,或在末端的下一个元素。

Iter1-iter2

用来计算两个迭代器之间的距离,其结果为difference_type类型,signed,类似于size_type

int main()
{
	vector<int> ivec(10);
	vector<int>::difference_type dis;
	vector<int>::iterator iter1, iter2;
	iter1 = ivec.begin();
	iter2 = ivec.end();
	dis = iter2 - iter1;
	cout << dis << endl;
	dis = iter1 - iter2;
	cout << dis << endl;
	getchar();
	return 0;
}
可以用迭代器算术操作来移动迭代器指向容器中的某个元素:

Iter=vec.begin()+vec.size()/2;

迭代器指向容器中中间位置的元素(容器中有奇数个,指向中间位置;偶数个,指向中间位置的后一个)

注意:在进行push_back操作后就不能在信赖iterator指向的值了。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值