即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

C++标准库类型vector

编程语言 sinat_16709955 14℃ 0评论
本文目录
[隐藏]

标准库类型vector表示对象的集合,集合中的每个对象都有一个与之对应的索引用于访问对象,所以常被称作容器(container)。使用如下声明以使用vector:

#include 
using std::vector;

C++既有类模板也有函数模板,vector是一个类模板。编译器根据模板创建类或者函数的过程称为实例化( instantiation),当使用模板时,需要指出编译器应把函数或者类实例化为何种类型。


对于类模板,需要提供一些额外信息,如下:

vector<int> ivec;
vector<string> svec;
vector<vector<string>> file;

vector能容纳绝大多数类型的对象作为其元素,但由于引用不是对象,所以不存在包含引用的vector,绝大多数内置类型或者类类型都可构成vector对象,甚至组成vector的元素也可以是vector。


早起版本的C++中,如果组成vector的元素还是vector或者其他模板类型,则其定义与C++11新标准有些不同。过去的定义方式必须在外层vector的右尖括号与其元素类型之间加一个空格,如:

vector<vector<string> > file;

1.定义和初始化

有如下几种方式定义和初始化vector:

vector v1;                   //默认初始化,v1不含任何元素
vector v2(v1);               //v2中包含v1中所有元素的副本
vector v2 = v1;              //与上相同
vector v3(n, val);           //包含n个重复的元素,每个元素的值都是val
vector v4(n);                //包含了n个地执行了值初始化的对象
vector v5{a, b, c};          //列表初始化,包含了初始值个数的元素,每个元素被赋予相应的初始值
vector v6={a, b, c};         //与上相同

允许把一个vector对象拷贝给另外一个vector对象,此时,新vector对象的元素就是原vector对象对应元素的副本,但是两个vector对象的类型必须相同。


如果提供的是初始值元素的列表,则只能把初始值都放在花括号里面进行初始化,而不能放在圆括号里面:

vector<string> v1{"a", "bb", "ccc"};        //正确
vector<string> v1("a", "bb", "ccc");        //错误

如果只提供元素数量而略去初始值,此时,库会创建一个值初始化的元素初值,并把它赋给容器中所有的元素。如vector对象的元素类型是内置类型,比如int则元素初始值自动设为0,如果是某种类类型,则元素由类默认初始化。如果vector对象中的元素的类型不支持默认初始化,就必须提供初始元素值,对于该种类型的对象来说,只提供元素数量而不设定初始值无法完成初始化工作。


某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。如:

vector<int> v1(10);                         //10个元素,每个元素都是0
vector<int> v2{10};                         //1个元素,值为10
vector<int> v3(10, 1);                      //10个元素,每个元素都是1
vector<int> v4{10, 1};                      //2个元素,分别为10和1

如果使用圆括号,可以说提供的值是用来构造(construct)vector对象的。如果用的是花括号,可以表述为想要使用列表初始化(list initialize)该vector对象,即尽可能的把花括号内的值当成是元素初始值的列表来处理,只有在无法进行列表初始化是才会考虑其他初始化方式。


如果使用了花括号的形式但是提供的值又不能用来列表初始化,就要考虑用这样的值来构造vector对象了。如:

vector<string> v1{"hi"};                    //列表初始化
vector<string> v2("hi");                    //错误,不可使用字面值字符串构建vector对象
vector<string> v3(10);                      //v3有10个默认初始化的元素
vector<string> v4{10, "hi"};                //v4有10个值为"hi"的元素

确认无法使用列表初始化之后,编译器会尝试使用默认值初始化vector对象。

2.添加元素

可以使用push_back函数向vector中添加元素,该函数负责将一个值当成vector对象的尾元素压到vector对象的尾端,如:

vector<int> v2;
for (int i = 0; i < 10; ++i) {
    v2.push_back(i);
}

C++标准要求vector应该能在运行时高效快速的添加元素,在定义vector对象时设定其大小会使其性能更差,只有一种例外,即所有元素值都一样的情况。一旦元素的值有不同,更有效的方法是先定义一个空的vector对象,再在运行时添加具体值。


vector的使用有很多隐含的要求,如:


如果循环体内部包含有向vector对象添加元素的语句,则不能使用范围for循环。范围for循环不应改变其所遍历序列的大小。

3.其他操作

包括如下一些操作,大致与string的操作类似:

v.empty()               //若v中不含任何元素则判断为真,否则为假
v.size()                //返回v中元素的个数
v.push_back(t)          //向v的末尾添加元素t
v[n]                    //返回v中第n个位置上的元素的引用
v1 = v2                 //用v2中元素的拷贝替换v1中的元素
v1 = {a,b,c...}         //用列表中元素的拷贝替换v1中的元素
v1 == v2                //当且仅当它们的元素数量相同且对应位置的元素值都相同时为真
<,<=,>,>=               //按字典序进行比较

访问vector中元素方法与访问string对象中字符的方法差不多,如:

vector<int> v{1,2,3,4,5,6,7,8,9};
for (auto &i : v) {
    i += 10;
}
for (auto i : v) {
    cout << i << endl;
}

vector的empty和size两个函数与string的同名成员功能完全一致,注意size返回vector中元素个数,返回值的类型是由vector定义的size_type类型,如:

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

要使用size_type需首先指定它是由哪种类型定义的,vector对象的类型总是包含这元素的类型。


关系运算符按照字典顺序进行比较:如果两个vector对象的容量不同,但是相应位置上的元素都一样,则元素较少的vector对象小于元素较多的vector对象;若元素的值有区别,则其大小关系由第一对相异的元素值的大小关系决定。只有当元素的值可以比较时,vector对象才能被比较。


使用下标运算符可以获取到指定的元素,但是不能使用下标形式来添加元素,string对象也是如此。只能对确定已知存在的元素进行下标操作,试图使用下标来访问一个不存在的元素将引发错误,不过这种错误不会被编译器发现,而是在运行时产生一个不可预知的值。缓冲区溢出(buffer overflow)指的就是这类错误。

转载请注明:CodingBlog » C++标准库类型vector

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情