首页 > 编程语言 >C++ 标准库中的 vector

C++ 标准库中的 vector

时间:2023-03-10 22:45:33浏览次数:38  
标签:10 初始化 对象 元素 C++ v1 vector 库中

标准库类型 vector 表示对象的集合,其中所有对象的类型都相同。
集合中的每个对象,都有一个与之对应的索引,索引用于访问对象。
vector 是一个类模板,编译器根据模板创建类或者函数的过程称为 实例化 (instantiation)
vector 是模板而非类型,由 vector 生成的类型必须包含 vector 中元素的类型,例如 vector
vector 能够容纳绝大多数类型的对象作为其元素,但是因为引用不是对象。所以不存在包含引用的 vector

需要指出的是,在早期版本的 C++ 标准中,如果 vector 的元素还是 vector (或者其他模板类型),其定义的形式与现在的 C++ 11 新标准略有不同。过去,必须在外层 vector 对象的右尖括号和其他元素类型之间添加一个空格,如应该写成 vector<vector<int> > 而非 vector<vector<int>>
一些老的编译器可能还存在这方面的要求

定义和初始化 vector

初始化 vector 方法
vector v1 v1 是一个空 vector,它潜在的元素类型是 T 类型,执行默认初始化
vector v2(v1) v2 中有 v1 所有元素的副本
vector v2 = v1 等价于 v2(v1),v2 中有 v1 所有元素的副本
vector v3(n, val) v3 包含了 n 个重复的元素,每个元素的值都是 val
vector v4(n) v4 包含了 n 个重复地执行了值初始化的对象
vector v5 v5 包含了初始值个数的元素,每个元素被赋予相应的初始值
vector v5 = 等价 v5

列表初始化 vector 对象

C++ 11 新标准还提供了另外一种为 vector 对象的元素赋初值的方法,即列表初始化。此时,用花括号括起来的 0 个或者多个初始值被赋给 vector 对象。
vector<string> articles = {"a", "an", "the"};
上述 vector 对象包含三个元素:第一个是字符串 "a" 第二个是字符串 "an" 第三个是字符串 "the"
C++ 提供了几种不同的初始化的方式,大多数情况下这些初始化的方式可以互相等价的使用,不过也并非一直如此。其一,使用拷贝初始化时(即使用 = 时)只能提供一个初始值;其二,如果提供的是一个类内初始值,则只能使用拷贝初始化或使用花括号的形式初始化。第三种特殊的要求是,如果提供的是初始元素的列表,则只能把初始值都放在花括号里进行列表初始化,而不能放在圆括号里:

vector<string> v1{"a", "an", "the"};	// 列表初始化
vector<string> v2("a", "an", "the");	// 错误

创建指定数量的元素

可以用 vector 对象容纳的元素数量和所有元素的统一初始值来初始化 vector 对象

vector<int> ivec(10, -1);			// 包含 10 个 -1 的 vector
vector<string> svec(10, "hi");		// 包含 10 个 hi 的 vector

值初始化
通常情况下,可以只提供 vector 对象容纳的元素数量而略去初始值,此时库会创建一个 值初始化 (value-initialized) 的元素初值,并把它赋值给容器中的所有元素。

vector<int> ivec(10);
vector<string> svec(10);

对于这种初始化的方式有两个特殊的限制:其一,有些类要求必须明确地提供初始值,如果 vector 对象中元素的类型不支持默认初始化,我们就必须提供初始化的元素值。对这种类型的对象来说,只提供元素的数量而没有设定初始值无法完成初始化的工作。
其二,如果只提供了元素的数量而没有设定初始值,只能使用直接初始化:
vector<int> vi = 10; // 错误:必须使用直接初始化的形式指定向量大小
列表初始化值还是元素数量?
在某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。例如

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 包含一个元素 "hi"
vector<string> v6("hi");	// 错误 无法通过这种方式初始化 vector
vector<string> v7{10};		// v7 拥有 10 个空字符串
vector<string> v8{10, "hi"};// v8 拥有 10 个 "hi"

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

向 vector 对象中添加元素

push_back 往 vector 尾部添加元素。示例

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

关键概念: vector 对象能高效增长
C++ 标准要求 vector 应该能在运行时高效快速地添加元素。因此既然 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 = 用列表中元素的拷贝替换 v1 中的元素
v1 == v2 v1 和 v2 相等当且仅当它们的元素数量相同且对应位置的元素值都相同
v1 != v2
<, <=, >, >=
顾名思义,以字典顺序进行比较

vector 的 empty 和 size 两个成员与 string 的同名成员功能完全一致: empty 检查 vector 对象是否包含元素然后返回一个布尔值;size 则返回 vector 对象中元素的个数,返回值的类型是由 vector 定义的 size_type 类型。
要使用 size_type 需要首先指定它是由哪种类型定义的。 vector 对象的类型总是包含着元素的类型

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

各个相等性运算符和关系运算符也与 string 的相应运算符功能一致。若元素的值有区别,则 vector 对象的大小关系由第一对相异的元素值的大小关系决定。同时,只有当元素的值可以比较时,vector 对象才能被比较。
vector 与索引
同时值得注意的是,不能通过 v[n] 这种下标读取的方式去添加元素。正确的方式是使用 push_back
无论是 vector 对象还是 string 对象,下标运算符可用于访问已存在的元素,而不能用于添加元素。
同时值得注意的是,只能对已存在的元素执行下标操作!
关于下标必须明确的一点是:只能对确知已存在的元素执行下标操作。例如,

vector<int> ivec; 	// 空 vector 对象
cout << ivec[0];	// 错误 ivec 不包含任何元素
vector<int> ivec2(10);	// 包含 10 个 0 的 vector 对象
cout << ivec2[10];		// 错误 ivec2 元素的合法索引从 0 到 9

试图用下标的形式去访问一个不存在的元素将引发错误,不过这种错误不会被编译器发现,而是在运行时产生一个不可预知的值。
不幸的是,这种通过下标访问的存在的元素的行为非常常见,而且会产生很严重的后果。所谓的缓冲区溢出 (buffer overflow) 指的就是这类错误,这也是导致 PC 及其他设备上应用程序出现安全问题的一个重要原因。
确保下标合法的一种有效手段就是尽可能使用范围 for 语句。for(auto& i : vec){ ... }

标签:10,初始化,对象,元素,C++,v1,vector,库中
From: https://www.cnblogs.com/manqing321/p/17204876.html

相关文章

  • C++ | 計算兩點的角度
    #include<math.h>#include<iostream>#include<stdio.h>#definePI3.141592654#defineEARTH_RADIUS6378.137//地球近似半徑u......
  • C++协程
    参考C++那些事之C++20协程#include<iostream>#include<coroutine>structgenerator{structpromise_type{intcurrent_value;std::suspend......
  • C/C++小学生测验[2023-03-10]
    C/C++小学生测验[2023-03-10]题目2:小学生测验面向小学1~2年级学生,随机选择两个整数和加减法形成算式要求学生解答。功能要求:(1)进入测试之前先输入用户名、密码登录,......
  • C++的常量
    在C++中,常量可以分为以下几种类型:1、整型常量(IntegerConstants):整数常量,可以是十进制、八进制或十六进制,例如42、052、0x2A等。整型常量可以使用后缀来指定类型。u......
  • 如何通过C++ 将数据写入 Excel 工作表
    直观的界面、出色的计算功能和图表工具,使Excel成为最流行的个人计算机数据处理软件。在独立的数据包含的信息量太少,而过多的数据又难以理清头绪时,制作成表格是数据管理的最......
  • C++ 数组 指针小记
    voidfun(int*aa){return;}int*a=newint[16];memset(a,0,16);fun(a);voidfun(int*aa){return;}inta[16]={0};fun(a);  总之,两......
  • matlab2c使用c++实现matlab函数系列教程-sort函数
    ​​​​全栈工程师开发手册(作者:栾鹏)​​matlab2c动态链接库下载​​​matlab库函数大全matlab2c基础教程matlab2c开发全解教程matlab2c调用方法:1、下载动态链接库2、......
  • matlab2c使用c++实现matlab函数系列教程-trace函数
    ​​​​全栈工程师开发手册(作者:栾鹏)​​matlab2c动态链接库下载​​​matlab库函数大全matlab2c基础教程matlab2c开发全解教程matlab2c调用方法:1、下载动态链接库2、......
  • matlab2c使用c++实现matlab函数系列教程-reshape函数
    ​​​​全栈工程师开发手册(作者:栾鹏)​​matlab2c动态链接库下载​​​matlab库函数大全matlab2c基础教程matlab2c开发全解教程matlab2c调用方法:1、下载动态链接库2、......
  • matlab2c使用c++实现matlab函数系列教程-triu函数
    ​​​​全栈工程师开发手册(作者:栾鹏)​​matlab2c动态链接库下载​​​matlab库函数大全matlab2c基础教程matlab2c开发全解教程matlab2c调用方法:1、下载动态链接库2、......