C++ vector 初始化

在 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;

上一篇:

下一篇:

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号