11.17 — 动态数组 std::vector 简介
Key Takeaway
在之前的课程中我们介绍了std::array
,它提供了C++内建固定数组相同的功能,但是更安全也更好用。
类似地,C++ 标准库也提供了相应的功能,使得使用动态数组可以更加安全和易用。这个功能就是 std::vector
。
不同于std::array
尽可能仿照固定数组的功能,std::vector
则提供了很多数组的额外功能,因此 std::vector
也成为了C++中最有用的工具之一。
std::vector
简介
std::vector
在C++03中被引入,它提供了dynamic-array的功能并且可以自我管理内存的申请和释放。也就是说,你可以在运行时创建数组并指定其长度,而不需要使用new
和delete
来手动管理内存的申请释放。std::vector
位于 <vector>
头文件中。
声明一个 std::vector
很简单:
1 2 3 4 5 6 7 8 9 |
|
注意,不论是初始化与否,你都不需要在编译时指定数组长度。这是因为 std::vector
可以在需要时自行分配内存。
和 std::array
一样,访问数组元素可以使用下标运算符(不进行越界检查)或at()
函数(进行越界检查)访问:
1 2 |
|
对于上面两种情况,如果你访问超出数组结尾的元素,vector并不会自动调整长度。
在 C++11 中,你可以使用初始化值列表为 std::vector
赋值:
1 2 |
|
对于这种情况,vector可以根据元素的个数调整其长度。
自我清理,避免内存泄漏
当一个vector变量超出作用域时,它会自动释放它所使用的内存(如果有必要)。这不仅方便(因为您不必自己做),还有助于防止内存泄漏。考虑下面的代码片段:
1 2 3 4 5 6 7 8 9 10 11 |
|
COPY
如果 earlyExit
被设置为 true
,则数组的内存不会被释放,会造成内存泄漏。
但是,如果 array
是 std::vector
的话,就不会出现问题,因为 array
会在离开作用域时自动释放内存(不论函数是否正确退出)。这也说明使用 std::vector
比自己管理内存要更加安全。
Vectors 能够保存其长度信息
不同于内建的动态数组(不知道其指向数组的程度),std::vector
能够保存其长度。使用 size()
函数就可以得知 vector 的长度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
输出结果为:
1 2 |
|
和std::array
一样,size()
返回的是size_type
类型的值 (完整的形式为 std::vector<int>::size_type
),它是无符号整型数。
调整 vector 大小
调整内置的动态数组的大小是很复杂的,而调整std::vector
的大小则很简单,调用resize()
即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
打印:
1 2 |
|
有两件事需要注意。首先,当调整 vector 的大小时,已经存在的元素会被保存下来。第二,新的元素会被初始化为该类型的默认值(整型是0)。
Vectors 的大小也可以缩小:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
打印结果:
1 2 |
|
调整vector大小的开销是很大的,因此应该尽量少做。如果你需要一个具有特定数量元素的向量,但在声明时不知道元素的值,你可以创建一个具有默认元素的向量,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
打印:
1 2 |
|
小贴士
我们会在 16.7 - std::initializer_list 中介绍直接初始化和括号初始化的不同。经验法则是:对于你不想初始化的列表型类型,使用直接初始化。
压缩布尔值
std::vector
还有另外一个很酷的小特性,它会把8个布尔类型的元素压缩为一个字节!这一切都是在幕后完成的,对你使用 std::vector
并没有影响。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
打印结果:
1 2 |
|
更多内容
注意,本节课只是对 std::vector
进行简介,在 12.3 - std::vector的容量和类栈行为中,我们会介绍它的一些额外的功能,包括长度和容量的区别,并且详细介绍std::vector
是如何管理内存的。
结论
因为std::vector
类型是变量可以自己管理内存(有助于避免内存泄漏)并且能够记录自身长度,所以我们推荐在大多数需要使用动态数组的时候,使用std::vector
。