@@ -19,17 +19,65 @@ order: 4
19
19
1 . 为什么要引入 ` std::array ` 而不是直接使用 ` std::vector ` ?
20
20
2 . 已经有了传统数组,为什么要用 ` std::array ` ?
21
21
22
- 先回答第一个问题,` std::vector ` 太强大了,以至于我们没有必要为了去敲碎一个鸡蛋而用一个钉锤。使用 ` std::array ` 保存在栈内存中,相比堆内存中的 ` std::vector ` ,我们就能够灵活的访问这里面的元素,从而获得更高的性能;同时正是由于其堆内存存储的特性,有些时候我们还需要自己负责释放这些资源 。
22
+ 先回答第一个问题,与 ` std::vector ` 不同, ` std::array ` 对象的大小是固定的,如果容器大小是固定的,那么可以优先考虑使用 ` std::array ` 容器。另外由于 ` std:: vector` 是自动扩容的,当存入大量的数据后,并且对容器进行了删除操作,容器并不会自动归还被删除元素相应的内存,这时候就需要手动运行 ` shrink_to_fit() ` 释放这部分内存 。
23
23
24
- 而第二个问题就更加简单,使用` std::array ` 能够让代码变得更加现代,且封装了一些操作函数,同时还能够友好的使用标准库中的容器算法等等,比如 ` std::sort ` 。
24
+ ``` cpp
25
+ std::vector<int > v;
26
+ std::cout << " size:" << v.size() << std::endl; // 输出 0
27
+ std::cout << " capacity:" << v.capacity() << std::endl; // 输出 0
28
+
29
+ // 如下可看出 std::vector 的存储是自动管理的,按需自动扩张
30
+ // 但是如果空间不足,需要重新分配更多内存,而重分配内存通常是性能上有开销的操作
31
+ v.push_back(1 );
32
+ v.push_back(2 );
33
+ v.push_back(3 );
34
+ std::cout << " size:" << v.size() << std::endl; // 输出 3
35
+ std::cout << " capacity:" << v.capacity() << std::endl; // 输出 4
36
+
37
+ // 这里的自动扩张逻辑与 Golang 的 slice 很像
38
+ v.push_back(4 );
39
+ v.push_back(5 );
40
+ std::cout << " size:" << v.size() << std::endl; // 输出 5
41
+ std::cout << " capacity:" << v.capacity() << std::endl; // 输出 8
42
+
43
+ // 如下可看出容器虽然清空了元素,但是被清空元素的内存并没有归还
44
+ v.clear();
45
+ std::cout << " size:" << v.size() << std::endl; // 输出 0
46
+ std::cout << " capacity:" << v.capacity() << std::endl; // 输出 8
47
+
48
+ // 额外内存可通过 shrink_to_fit() 调用返回给系统
49
+ v.shrink_to_fit();
50
+ std::cout << " size:" << v.size() << std::endl; // 输出 0
51
+ std::cout << " capacity:" << v.capacity() << std::endl; // 输出 0
52
+ ```
53
+
54
+ 而第二个问题就更加简单,使用 ` std::array ` 能够让代码变得更加“现代化”,而且封装了一些操作函数,比如获取数组大小以及检查是否非空,同时还能够友好的使用标准库中的容器算法,比如 ` std::sort ` 。
25
55
26
- ` std::array ` 会在编译时创建一个固定大小的数组, ` std::array ` 不能够被隐式的转换成指针, 使用 ` std::array ` 很简单,只需指定其类型和大小即可:
56
+ 使用 ` std::array ` 很简单,只需指定其类型和大小即可:
27
57
28
58
``` cpp
29
- std::array<int , 4 > arr= {1,2,3,4};
59
+ std::array<int , 4 > arr = {1, 2, 3, 4};
60
+
61
+ arr.empty(); // 检查容器是否为空
62
+ arr.size(); // 返回容纳的元素数
63
+
64
+ // 迭代器支持
65
+ for (auto &i : arr)
66
+ {
67
+ // ...
68
+ }
69
+
70
+ // 用 lambda 表达式排序
71
+ std::sort (arr.begin(), arr.end(), [ ] (int a, int b) {
72
+ return b < a;
73
+ });
74
+
75
+ // 数组大小参数必须是常量表达式
76
+ constexpr int len = 4 ;
77
+ std::array<int , len> arr = {1, 2, 3, 4};
30
78
31
- int len = 4;
32
- std::array< int, len> arr = {1,2,3,4}; // 非法, 数组大小参数必须是常量表达式
79
+ // 非法,不同于 C 风格数组,std::array 不会自动退化成 T *
80
+ // int * arr_p = arr;
33
81
```
34
82
35
83
当我们开始用上了 `std::array` 时,难免会遇到要将其兼容 C 风格的接口,这里有三种做法:
0 commit comments