您的位置:首页 > 编程语言 > C语言/C++

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

2015-05-12 21:30 344 查看
1.标准库vector类型

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

vector称之为容器。

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

#include <vector>
using std::vector;


vector是一个类模板,因此可以定义string对象的vector,int对象的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(元素)到vector的back

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返回的迭代器指向末端元素的下一个,它指向了一个容器中不存在的元素。若容器为空,则begin和end返回的迭代器相同。

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是可以变化的:迭代器指向的位置可以发生变化,但迭代器指向的位置的值不能够发生变化

Const的vector容器的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指向的值了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: