标准库类型vector表示对象的集合,其中所有对象的类型相同。
vector将元素保存在连续的内存空间中。
我们可以将标准库vector看做动态的数组,相比于一般的数组——其维度必须提前给定——动态数组vector并没有限制其大小,这表明我们可以自由的先向其中添加元素。
学习标准库类型vector之前,我们必须了解函数模板和类模板。
定义和初始化vector
默认初始化vector对象
vector<T> v1; v1是一个空vector,它潜在的元素是T类型的,执行默认初始化。
值得注意的是,最常用的方式就是先定义一个空vector,然后当运行时获取到元素的值后,再逐一添加。
定义vector对象时指定元素的初始值
vector<T> v2(v1); v2中包含有v1所有元素的副本。
vector<T> v2 = v1; v2中包含有v1所有元素的副本。
注意,两个vector对象的类型必须相同。
创建指定数量的元素
vector<T> v3(n,val); v3中包含了n个重复的元素,每个元素的值都是val。
vector<T> v4(n); v4中包含了n个重复的元素,每个元素都是执行值初始化的对象。
通常情况下,可以只提供vector对象容纳的元素数量而略去初始值,此时标准库会创建一个值初始化的元素初值,并把它赋值给容器中的所有元素。
这个初值由vector对象中的元素的类型决定。
- 如果vector对象的元素是内置类型,比如int,则元素初始值自动设为0;
- 如果vector对象的元素是某种类类型,则元素由类默认初始化;
注意:
- 如果vector对象中元素的类型不支持默认初始化,我们必须提供初始化的元素值。
- 如果只提供了元素的数量而没有设定初始值,我们只能使用直接初始化。
列表初始化vector对象
vector<T> v5{a,b,c...}; v5包含了初始化值个数的元素,每个元素被赋予相应的初始值。
vector<T> v5 = {a,b,c...}; v5包含了初始化值个数的元素,每个元素被赋予相应的初始值。
C++11新标准提供了一种为vector对象的元素赋初值的方法——列表初始化。
此时,用花括号括起来的0个或多个初始元素值被赋予vector对象。
注意
在某些情况下,初始化的真实含义依赖于传递初始值用的是花括号{}还是圆括号()。
- 如果用的是圆括号,可以说提供的值是用来构造vector对象的。
- 如果用的是花括号,
- 可以表述成我们想列表初始化vector对象,即尽可能地把花括号内的值当成元素初始值的列表来处理。
- 在无法执行列表初始化时,我们考虑用这样的值来构造vector对象了。
vector<int > v1(10); /*v1有10个元素,每个值都是0*/
vector<int > v2{10}; /*v2有一个元素,值是10*/
vector<int > v3(10,1); /*v3有10个元素,每个值都是1*/
vector<int > v4{10,1}; /*v4有2个元素,值分别为10和1*/
vector<string> v5{"hi"}; /*列表初始化,v5有一个元素*/
vector<string> v6("hi"); /*错误*/
vector<string> v7(10); /*v7有10个默认初始化的元素*/
vector<string> v8{10,"hi"}; /*v8有10个值为“hi”的元素*/
向vector对象中添加元素
push_back函数
利用vector的成员函数push_back向vector中添加元素。
push_back负责把一个值当成vector对象的尾元素“压入”vector对象的“尾端”。
vector<int > v2;
for (int i = 0; i != 100; ++i) {
v2.push_back(i);
}
insert函数
利用vector的成员函数insert可以向容器中的任意位置插入0个或多个元素。
insert(p , t) 在迭代器p指向的元素之前插入一个值为t的元素
insert(p , n , t) 在迭代器p指向的元素之前插入n个值为t的元素
insert(p , b , e) 在迭代器p指向的元素之前插入迭代器b和e指定范围内的元素
insert(p , list) 在迭代器p指向的元素之前插入一个花括号包围的元素值列表
insert函数返回指向第一个新加入元素的迭代器。
vector<string> v = {"quasi" , "simba" , "frollo" , "scar"};
v.insert(v.begin() , "xiong");
v.insert(v.end() , 3 , "hupu");
v.insert(v.begin() , v.end()-2 , v.end());
v.insert(v.end() , {"these" , "words" , "will" , "go" , "at" , "the" , "end"});
for (int i = 0; i != 17; ++i) {
cout << v[i] << endl;
}
注意
刚接触C++语言的程序员也许会认为可以通过vector对象的下标形式来添加元素,事实并非如此。
关于下标运算必须明确一点:只能对确知已存在的元素执行下标操作。任何试图用下标的形式去访问一个不存在的元素将引发错误。
vector对象的下标运算符可用于访问已存在的元素,而不能用于添加元素。
从vector对象中删除元素
pop_back函数
利用vector的成员函数pop_back从vector中删除元素。
pop_back负责删除vector中的尾元素。
for (int j = 0; j != 50; ++j) {
v2.pop_back();
}
erase函数
成员函数erase从容器中指定位置删除元素。
erase(p) 删除迭代器p所指定的元素
erase(b , e) 删除迭代器b和e所指定范围内的元素
返回指向删除的(最后一个)元素之后位置的迭代器。
vector<string> v = {"quasi" , "simba" , "frollo" , "scar"};
v.insert(v.begin() , "xiong");
v.insert(v.end() , 3 , "hupu");
v.insert(v.begin() , v.end()-2 , v.end());
v.insert(v.end() , {"these" , "words" , "will" , "go" , "at" , "the" , "end"});
v.erase(v.begin());
v.erase(v.begin() , v.begin() + 10);
for (int i = 0; i != 6; ++i) {
cout << v[i] << endl;
}
clear函数
删除容器中所有元素。
返回void。
访问vector对象的元素
在容器中访问元素的成员函数返回的都是引用!
- 如果容器时一个const对象,则返回值是const的引用。
- 如果容器不是const的,则返回值是普通引用,我们可以用来改变元素的值。
c.back() 返回尾元素的引用
c.front() 返回首元素的引用
c[n] 返回下标为n的元素的引用
c.at(n) 返回下标为n的元素的引用
vector<int > c = {1,2,3,4,5,6,7,8};
if (!c.empty())
{
c.front() = 42;
auto &v = c.back();
v = 1024;
auto v2 = c.back();
v2 = 0;
}
for (int i = 0; i < 8; ++i) {
cout << c[i] << endl;
}
vector对象的大小操作
size函数
成员函数size返回vector对象中元素的个数
empty函数
对成员函数empty而言,如果vector对象中不含有元素,返回真;否则,返回假。
max_size函数
返回一个大于或者等于该类型容器所能容纳的最大元素数的值。
vector对象的赋值
assign函数
顺序容器定义了一个名为assign的成员函数,允许我们从一个不同但相容的类型赋值,或者从容器的一个子序列赋值。
seq.assign(b , e) 将seq中的元素替换为迭代器b和e所表示的范围中的元素
seq.assign(list) 将seq中的元素替换为列表初始化list中的元素
seq.assign(n , t) 将seq中的元素替换为n个值为t的元素
vector<string> vec ;
vector<string> vec1 = {"i" , "am" , "xxx" , "jjj" , "kkk"};
vec.assign(vec1.begin()+1 , vec1.end()-1);
vec.assign(10 , "hi");
for (int i = 0; i < 10; ++i) {
cout << vec[i] << endl;
}
swap函数
swap操作交换两个相同类型容器的内容。
调用swap之后,两个容器中的元素会交换。
容器既提供了成员函数版本的swap,也提供了非成员函数版本的swap。建议使用非成员版本的swap。