在 C++ 中,创建 vector 容器时,我们可以在定义的同时指定它的初始元素或初始长度。这个赋初值的过程就叫做 “初始化”。
在前面学习数组初始化时,我们主要是使用花括号列出初始值,而 vector 的初始化方式要灵活得多。日常开发中最常用的有以下 4 种方式:① 默认初始化;② 使用花括号 {} 初始化;③ 使用圆括号 () 初始化;④ 使用已有的 vector 初始化。
默认初始化
如果在创建 vector 时暂时还没有准备好具体数据,最简单的做法就是先定义一个空容器。等后面有了数据,我们再调用 push_back() 等函数往里面添加元素。
语法:
std::vector<数据类型> 容器名;说明:
这种写法不会放入任何初始元素,创建出来的是一个空的 vector,调用 size() 返回的元素数量为 0。
示例 1:创建空 vector
#include <iostream>
#include <vector>
int main() {
std::vector<int> v;
std::cout << "元素数量:" << v.size() << '\n';
return 0;
}运行结果如下。
元素数量:0分析:
std::vector<int> v; 表示定义了一个名为 v 的空容器。由于里面还没有存放任何元素,调用 v.size() 返回的结果是 0。
使用花括号 {} 初始化
当我们已经知道 vector 一开始具体要保存哪些数据时,使用花括号 {} 初始化是最直观的写法。花括号里面写的内容就像一张 “元素清单”,写了哪些值,容器一开始就按顺序保存哪些元素。
语法:
std::vector<数据类型> 容器名 = {元素1, 元素2, ...};说明:
花括号中的各个元素之间使用英文逗号(,)隔开。如果花括号里什么都不写,也就是写成 std::vector<int> v = {};,效果与默认初始化完全一样,同样会创建一个空容器。
示例 2:使用花括号初始化
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<int> a = {18, 20, 22};
std::vector<std::string> b = {"C++", "Python"};
std::cout << a[0] << ' ' << a[1] << ' ' << a[2] << '\n';
std::cout << b[0] << ' ' << b[1] << '\n';
return 0;
}运行结果如下。
18 20 22
C++ Python分析:
在这个例子中,a = {18, 20, 22} 一共给出了 3 个整数,它们会按顺序保存在 a 中并依次打印出来。紧接着定义的容器 b 则按顺序保存了 "C++" 和 "Python" 两个字符串元素。
使用花括号初始化时,中间的等号 = 其实是可以省略的。对于上面这个例子来说,下面 2 种方式是等价的。
// 方式 1(推荐)
std::vector<int> a = {18, 20, 22};
// 方式 2
std::vector<int> a{18, 20, 22};方式 1 带有等号 =,与普通数组赋初值的书写习惯一致,阅读起来更加直观。因此在实际开发中,我们更推荐使用方式 1。
使用圆括号 () 初始化
有时候我们在创建 vector 时,只知道一开始需要多少个元素,或者希望所有元素都使用同一个初始值。这时我们就可以使用圆括号 () 来初始化。
1. 只指定元素数量
如果只希望先创建出指定数量的元素,我们可以在圆括号中传入一个表示数量的数字。
语法:
std::vector<数据类型> 容器名(元素数量);说明:
圆括号中的数字表示初始的元素个数。如果不额外指定初始值,C++ 会自动使用该数据类型的默认值来填充每一个元素:
- 数值类型:如
int、double,所有元素默认初始化为0或0.0。 - 字符串类型:如果元素是 std::string 类型,所有元素默认初始化为空字符串
""。
示例 3:只指定元素数量
#include <iostream>
#include <vector>
int main() {
std::vector<int> v(3);
std::cout << "元素数量:" << v.size() << '\n';
std::cout << v[0] << ' ' << v[1] << ' ' << v[2] << '\n';
return 0;
}运行结果如下。
元素数量:3
0 0 0分析:
v(3) 表示创建 3 个 int 元素,所以 v.size() 返回 3。由于我们没有指定初始值,这 3 个元素全部自动初始化为 0,创建好之后就可以直接通过下标 0 到 2 去读写。
2. 同时指定数量和初始值
如果我们不仅知道要创建多少个元素,而且希望这些元素一开始都等于同一个值,可以在圆括号中传入两个参数。
语法:
std::vector<数据类型> 容器名(元素数量, 初始值);说明:
圆括号里的第 1 个参数表示要创建的元素数量,第 2 个参数表示每个元素统一使用的初始值。
示例 4:指定数量和初始值
#include <iostream>
#include <vector>
int main() {
std::vector<int> v(3, 100);
std::cout << "元素数量:" << v.size() << '\n';
std::cout << v[0] << ' ' << v[1] << ' ' << v[2] << '\n';
return 0;
}运行结果如下。
元素数量:3
100 100 100分析:
v(3, 100) 表示创建 3 个 int 元素,并且把每个元素的初始值都设为 100。如果小伙伴们想批量创建 50 个初值为 1 的计数项,直接写成 std::vector<int> items(50, 1); 即可,不需要手动写 50 个 1。
此外,圆括号里的数量不仅可以直接写固定数字,还可以传入普通整型变量 n。比如写成 std::vector<int> v(n, 0);,就能在程序运行期间根据 n 的值动态决定容器的初始长度。
圆括号 () 与花括号 {} 的区别
在初始化 vector 时,初学者最容易混淆的就是圆括号 () 和花括号 {}。虽然看起来只是括号形状不同,但表达的意思完全不一样:圆括号 () 侧重指定 “元素数量”,而花括号 {} 则是直接列出 “具体元素”。最容易写混的 4 种形式如下表所示。
| 初始化写法 | 元素数量 | 实际元素 | 含义说明 |
|---|---|---|---|
| std::vector<int> v(3); | 3 | 0, 0, 0 | 创建 3 个元素,默认初值为 0 |
| std::vector<int> v = {3}; | 1 | 3 | 创建 1 个元素,该元素的值为 3 |
| std::vector<int> v(3, 10); | 3 | 10, 10, 10 | 创建 3 个元素,每个元素初值均为 10 |
| std::vector<int> v = {3, 10}; | 2 | 3, 10 | 创建 2 个元素,值分别为 3 和 10 |
示例 5:对比圆括号与花括号
#include <iostream>
#include <vector>
int main() {
std::vector<int> a(3, 10);
std::vector<int> b = {3, 10};
std::cout << "a 的元素数量:" << a.size() << '\n';
std::cout << a[0] << ' ' << a[1] << ' ' << a[2] << '\n';
std::cout << "b 的元素数量:" << b.size() << '\n';
std::cout << b[0] << ' ' << b[1] << '\n';
return 0;
}运行结果如下。
a 的元素数量:3
10 10 10
b 的元素数量:2
3 10分析:
从运行结果可以清楚地看出两者的差别:a(3, 10) 使用圆括号,第 1 个数字 3 代表数量,因此批量创建了 3 个值为 10 的元素。而 b = {3, 10} 使用花括号,里面的数字全部代表元素本身的值,因此只包含 3 和 10 这两个元素。
提示 在实际开发中,你只需要记住一个简单的判断标准:已经知道具体有哪些元素时,优先使用花括号 {};需要按 “指定数量” 批量创建元素时,使用圆括号 ()。
使用已有的 vector 初始化
如果程序中已经有一个同类型的 vector,我们也可以直接使用它来初始化一个新的 vector。
语法:
std::vector<数据类型> 新容器名 = 原容器名;说明:
除了使用等号 = 之外,写成圆括号形式 std::vector<数据类型> 新容器名(原容器名); 也是等价的,日常开发中一般使用更直观的 = 写法。复制好之后,新容器与原容器各自独立,修改其中一个不会影响另一个。
示例 6:复制已有的 vector
#include <iostream>
#include <vector>
int main() {
std::vector<int> a = {15, 25, 35};
std::vector<int> b = a;
b[0] = 99; // 修改 b 的首元素
std::cout << "a[0] = " << a[0] << '\n';
std::cout << "b[0] = " << b[0] << '\n';
return 0;
}运行结果如下。
a[0] = 15
b[0] = 99分析:
在这个例子中,std::vector<int> b = a; 在创建容器 b 时,把 a 里的 3 个元素完整复制了一份。随后我们将 b[0] 修改为 99,而原来的 a[0] 依然保持 15 不变,说明 a 和 b 保存的是两份互不干扰的数据。
这里小伙伴们要注意一点:使用已有容器初始化新容器时,两个 vector 尖括号里的元素类型必须完全一致。
虽然单个 int 整数可以自动转换为 double,但 std::vector<int> 和 std::vector<double> 属于两种不同的容器类型。下面这种跨类型初始化的写法是错误的,编译时会直接报错。
std::vector<int> a = {15, 25, 35};
std::vector<double> c = a;