C++ Primer:3.3 标准库类型vector

vector类型表示对象的集合,所有对象的类型都相同。
集合中的每个对象都有一个与之对应的索引,用于访问对象。
vector容纳着其他对象,也被称作容器。
使用vector必须包含适当的头文件。

#include <vector>
using std::vector

vector是一个类模板,模板不是类或函数。编译器根据模板创建类或函数的过程成为实例化,当使用模板时,需要指出把类和函数实例化成何种类型。
类模板需要提供一些额外的信息指定模板实例化为什么样的类,提供哪些信息由模板决定,模板名字后跟一对尖括号,括号内放上信息。
vector为例:

vector<int>ivec;     // ivec保存int类型的对象
vector<Sales item>Sales_vec;  // 保存Sales_item类型的对象
vector<vector<string>> file;  // 该向量的元素是vector对象
  • vector能容纳绝大多数类型的对象作为其元素,引用不是对象,不存在包含引用的vector。大多数内置类型和类都可以构成vector,也可以是vector<vector<>>

定义和初始化vector对象

vector对象初始化的方法:

vector<T> v1        // v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1)    // v2中包含有v1所有元素的副本
vector<T> v2 = v1   // 等价于v2(v1),v2中包含有v1所有元素的副本
vector<T> v3(n,val) // v3包含了n个重复的元素,每个元素的值都是val
vector<T> v4(n)   // v4包含了n个重复地执行了值初始化的对象
vector<T> v5{a,b,c...} // v5包含了初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v5 = {a,b,c...}  // 等价于v5{a,b,c...} 
  • 可以默认初始化vector对象,创建一个空vector
  • 最常见的方式是先定义一个空vector,运行时获取到元素的值后再逐一添加。
  • 定义vector对象时指定元素的初始值,允许把一个vector对象的元素拷贝给另一个vector对象。新的vector对象的元素是原vector对应元素的副本。两个vector对象的类型必须相同。

列表初始化vector对象

列表初始化:用花括号括起来的0个或多个初始元素被赋给vector对象。


C++几种不同的初始化方式,大多情况可以等价使用,除了:

  • 使用拷贝初始化时,只能提供一个初始值
  • 若提供的是类内初始值,只能使用拷贝初始化或花括号的形式初始化
  • 若提供的是初始元素值的列表,只能把初始值都放在花括号里进行列表初始化,不能放在圆括号里。
vector<string> vl{"a", "an", "the"}; //列表初始化
vector<string> v2("a", "an", "the"); //错误

创建指定数量的元素

vector对象容纳的元素数量和所有元素的统一初始值来初始化vector对象。vector<int> ivec{10, -1}; // 10个int类型的元素,每个都被初始化为-1

值初始化

可以只提供vector对象容纳的元素数量而不用略去初始值,此时库会创建一个值初始化元素初值,并把它赋给容器中的所有元素,初值由vector对象中的元素的类型决定。

  • 如果vector对象的元素是内置类型,int:初始值自动设为0
  • 如果元素是某种类,元素由类默认初始化,string:设置为空串
    两个特殊限制
  • 有些类明确要求提供初始值
  • 若只提供了元素的数量而没有设定初始值,只能使用直接初始化(不用=

列表初始值/元素数量

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

vector<int> v1(10);  // v1有10个元素,每个的值都是0
vector<int> v2{10};  // v2有1个元素,该元素的值是10
vector<int> v3(10, 1); // v3有10个元素,每个的值都是1
vector<int> v4{10, 1}; // v4有2个元素,值分别是10和1
  • 如果用的是圆括号,称提供的值是用来构造vector对象的。
  • 如果用的是花括号,表述为我们想列表初始化该vector对象。
  • 如果初始化时使用了花括号但提供的值又不能用来列表初始化,就考虑用这样的值来构造vector对象了。
vector<string> v5{"hi"}; // 列表初始化:v5有一个元素
vector<string> v6("hi"); // 错误:不能使用字符串字面值构建vector对象
vector<string> v7{10};  // v7有10个默认初始化的元素
vector<string> v8{10, "hi"}; // v7有10个默认初始化的元素

要执行列表初始化vector对象,花括号的值必须与元素类型相同;确认无法执行列表初始化后,编译器尝试使用默认初始化vector对象。


vector<int> v1;           // 空
vector<int> v2(10);       // 10个0
vector<int> v3(10, 42);   // 10个42
vector<int> v4{10};       // 1个10
vector<int> v5{10, 42};   // 2个元素 10,42
vector<string> v6{10};    // 10个空串
vector<string> v7{10, "hi"}; // 10个“hi”

vector对象中添加元素

对于vector对象,直接初始化的方式适用于三种情况:

  • 初始值已知且数量较少
  • 初始值是另一个vector对象的副本
  • 所有元素的初始值都一样
    更多的情况是:创建一个vector对象并不清楚实际的元素个数和元素的值;有些时候元素的初值已知,但这些值总量大且各不相同。
    创建一个空vector,运行时再利用vector的成员函数push_back向其中添加元素。push_back负责把一个值当成vector对象的尾元素push到vector对象的尾端。
vector<int> v2;   //空vector对象
for (int i = 0; i != 100; ++i)
	v2.push back(i);//依次把整数值放到v2尾端

string word; vector<string> text; //空 vector对象
while(cin>>word){
	text.push back(word); // 把word添加到text后面
}

vector对象能高效增长,元素的值有所不同,更有效的办法是定义一个空的vector,运行时向其添加具体的值。

vector对象添加元素蕴含的编程假定

必须确保所写的循环正确无误,特别是在循环有可能改变vector对象容量的时候。
如果循环内部包含向vector对象添加元素的语句,则不能使用范围for循环。

  • 范围for语句体内不应改变其所遍历序列的大小。

其他vector操作

vector支持的操作

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 // v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相同
v1 != v2
<,<=,>,>=  // 顾名思义,以字典顺序进行比较

使用范围for语句处理对象vector中的所有元素

vector<int> v;
for (auto &i : v)
	
for (auto i : v)
	

vectoremptysize两个成员与string同名成员的功能完全一致。

  • 使用size_type,需要首先指它是由哪种类型定义的。vector对象的类型总是包含着元素的类型。
vector<int>::size type // 正确
vector::size type      // 错误

各个相等性运算符和关系运算符也与string的相应运算符功能一致。

  • 两个vector对象相等当且仅当它们所含的元素个数相同,而且对应位置的元素值也相同。
    关系运算符依照字典顺序进行比较:
  • 如果两个vector对象的容量不同,但在相同位置上的元素值都一样,则元素较少的vector对象小于元素较多的vector 对象;
  • 若元素的值有区别,则 vector 对象的大小关系由第一对相异的元素值的大小关系决定。
    只有当元素的值可比较时,vector对象才能被比较。

计算vector内对象的索引

使用下标运算符能获取到指定的元素。

  • vector对象的下标也是从0开始,下标的类型是相应的size_type类型。
  • 只要vector对象不是一个常量,就能向下标运算符返回的元素赋值。
  • 可以计算得到对象的索引,直接获取索引位置上的元素。
  • 使用下标的时候必须清楚地知道它是否在合理的范围内。

不能用下标形式添加元素

vector<int> ivec; // 空vector对象
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
	ivec[ix] = ix; // 严重错误:ivec不包含任何元素

ivec是一个空的vector,根本不包含任何元素,也不能通过下标去访问任何元素。

for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
	ivec.push back(ix); // 正确:添加一个新元素,该元素的值是ix

vector对象(以及string)对象的下标运算符访问已存在的元素而不能用于添加元素。
只能读确知已存在的元素执行下标操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值