标准库 vector 类型

vector 是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。把 vector称为容器,是因为它可以包含其他对象。

使用 vector 之前,必须包含相应的头文件:

#include <vector>
using std::vector;

vector 是一个类模板(class template)。因此,可以定义保存 string 对象的 vector,或保存 int 值的 vector,又或是保存自定义的类类型对象vector。

声明从类模板产生的某种类型的对象,需要提供附加信息,信息的种类取决于模板。以 vector 为例,必须说明 vector 保存何种对象的类型,通过将类型放在类型放在类模板名称后面的尖括号中来指定类型:

vector<int> ivec; // ivec holds objects of type int
vector<Sales_item> Sales_vec; // holds Sales_items

vector 不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector 类型的每一种都指定了其保存元素的类型。因此,vector<int> 和 vector<string> 都是数据类型。

vector 对象的定义和初始化

vector<T> v1;

vector 保存类型为 T 对象。默认构造函数 v1 为空。

vector<T> v2(v1);

v2 是 v1 的一个副本。

vector<T> v2=v1;

与vector<T> v2(v1)等价

vector<T> v3(n, i);

v3 包含 n 个值为 i 的元素。

vector<T> v4(n);

v4 含有值初始化的元素的 n 个副本。

vector<T> v5{a,b,c…};

v5包含了初值个数的元素,每个元素被赋予相应的初始值。

vector<T> v5={a,b,c…};

等价于vector<T> v5{a,b,c…};

 

若要创建非空的 vector 对象, 必须给出初始化元素的值。当把一个 vector对象复制到另一个 vector 对象时, 新复制的 vector 中每一个元素都初始化为原 vectors 中相应元素的副本。但这两个 vector 对象必须保存同一种元素类型。

列表初始化vector对象

列表初始化是C++11中新定义的一种为vector对象的元素赋值,此时,用花括号括起来的0个或多个初始元素值被赋给vector对象:

vector<string> articles={“a”,“an”,“the”};

初始化的几点注意:

使用拷贝初始化时,只能提供一个初始值;

如果提供的是一个类内初始值,则只能使用拷贝初始化或使用花括号初始化;

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

vector<string> articles={“a”,“an”,“the”};       //列表初始化
vector<string> articles=(“a”,“an”,“the”);        //错误

创建确定个数的元素

可以用元素个数和元素值对 vector 对象进行初始化。构造函数用元素个数来决定 vector 对象保存元素的个数,元素值指定每个元素的初始值:

vector<int> ivec4(10, -1); // 10 elements, each initialized to -1
vector<string> svec(10, "hi!"); // 10 strings, each initialized to "hi!"

值初始化

如果没有指定元素的初始化式,那么标准库将自行提供一个元素初始值进行值初始化(value initializationd)。这个由库生成的初始值将用来初始化容器中的每个元素,具体值为何,取决于存储在 vector 中元素的数据类型。

如果 vector 保存内置类型(如 int 类型)的元素,那么标准库将用 0 值创建元素初始化式:

vector<int> fvec(10); // 10 elements, each initialized to 0

如果 vector 保存的是含有构造函数的类类型(如 string)的元素,标准库将用该类型的默认构造函数创建元素初始化式:

vector<string> svec(10); // 10 elements, each an empty string

如果只提供了元素的数量而没有设定初始值,只能使用直接初始化:

vector<int> vi=10;     //错误,必须使用直接初始化的形式指定向量大小

初始化值还是元素数量

用一个整数来初始化vector<int>时,整数的含义可能是vector对象的容量也可以是元素的值,可以使用花括号或圆括号来区分相应的定义:

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

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

如果使用的是花括号,即为列表初始化该vector对象,也就是说,初始化过程尽可能地把花括号内的值当成是元素初始值的列表来处理,只有在无法执行列表初始化时才会考虑其他初始化方式。

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

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

上面只有v5是列表初始化,要想列表初始化vector对象,花括号里的值必须与元素类型相同。v7和v8提供的值不能作为元素的初始值,因此编译器会尝试使用默认初始化方式来初始化vector对象。

向vector对象中添加元素

vector对象的初始化方式有三种:

初始值已知且很少;

初始化值是另一个对象的副本,元素值都一样;

更一般的情况是:创建一个vector对象时并不清楚实际所需要的元素个数,元素的值也无法确定,或者元素的初始值已知,但是这些值的数量较大且各不相同,那么创建vector对象的时候执行初始化操作显得过于繁琐。

push_back 操作接受一个元素值,并将它作为一个新的元素添加到 vector对象的后面,也就是“插入(push)”到 vector 对象的“后面(back)”:

// read words from the standard input and store them as elements in a vector

string word;
vector<string> text; // empty vector
while (cin >> word) {
text.push_back(word); // append word to text
}

虽然可以对给定元素个数的 vector 对象预先分配内存,但更有效的方法是先初始化一个空 vector 对象,然后再动态地增加元素。

其它对vector 对象的操作

v.empty()

如果 v 为空,则返回 true,否则返回 false。

v.size()

返回 v 中元素的个数

v.empty()

如果 v 为空,则返回 true,否则返回 false。

v.push_back(t)

在 v 的末尾增加一个值为 t 的元素。

v[n]

返回 v 中位置为 n 的元素。

v1 = v2

把 v1 的元素替换为 v2 中元素的副本。

v1 == v2

如果 v1 与 v2 相等,则返回 true。

!=, <, <=,>, and >=

保持这些操作符惯有的含义。

vector 对象的 size

成员函数size 返回相应 vector 类定义的 size_type 的值。使用 size_type 类型时,必须指出该类型是在哪里定义的。vector 类型总是包括总是包括 vector 的元素类型:

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

vector 的下标操作

vector 中的对象是没有命名的,可以按 vector 中对象的位置来访问它们。通常使用下标操作符来获取元素。

vector 的下标操作符接受一个值,并返回 vector 中该对应位置的元素。vector 元素的位置从 0 开始。下例使用 for 循环把 vector 中的每个元素值都重置为 0:

// reset the elements in the vector to zero
for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
ivec[ix] = 0;

下标操作不添加元素

不能使用vector 的下标操作添加元素,下标只能用于获取已存在的元素。

vector<int> ivec; // empty vector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)

ivec[ix] = ix;       //错误,不能使用下标操作添加元素

这个循环的正确写法应该是:

for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec.push_back(ix); // ok: adds new element with value ix
posted @ 2018-04-28 10:04  刘-皇叔  阅读(1746)  评论(0编辑  收藏  举报