You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: book/en-us/04-containers.md
+295-2
Original file line number
Diff line number
Diff line change
@@ -6,9 +6,302 @@ order: 4
6
6
7
7
# Chapter 04 Containers
8
8
9
-
[Table of Content](./toc.md) | [Previous Chapter](./03-runtime.md) | [Next Chapter: Smart Pointers and Memory Management](./05-pointers.md)
9
+
[TOC]
10
+
11
+
## 4.1 Linear Container
12
+
13
+
### `std::array`
14
+
15
+
When you see this container, you will definitely have this problem:
16
+
17
+
1. Why introduce `std::array` instead of `std::vector` directly?
18
+
2. Already have a traditional array, why use `std::array`?
19
+
20
+
First answer the first question. Unlike `std::vector`, the size of the `std::array` object is fixed. If the container size is fixed, then the `std::array` container can be used first.
21
+
In addition, since `std::vector` is automatically expanded, when a large amount of data is stored, and the container is deleted,
22
+
The container does not automatically return the corresponding memory of the deleted element. In this case, you need to manually run `shrink_to_fit()` to release this part of the memory.
The second problem is much simpler. Using `std::array` can make the code more "modern" and encapsulate some manipulation functions, such as getting the array size and checking if it is not empty, and also using the standard friendly. Container algorithms in the library, such as `std::sort`.
58
+
59
+
Using `std::array` is as simple as specifying its type and size:
60
+
61
+
```cpp
62
+
std::array<int, 4> arr = {1, 2, 3, 4};
63
+
64
+
arr.empty(); // check if container is empty
65
+
arr.size(); // return the size of the container
66
+
67
+
// iterator support
68
+
for (auto &i : arr)
69
+
{
70
+
// ...
71
+
}
72
+
73
+
// use lambda expression for sort
74
+
std::sort(arr.begin(), arr.end(), [](int a, int b) {
75
+
return b < a;
76
+
});
77
+
78
+
// array size must be constexpr
79
+
constexprint len = 4;
80
+
std::array<int, len> arr = {1, 2, 3, 4};
81
+
82
+
// illegal, different than C-style array, std::array will not deduce to T*
83
+
// int *arr_p = arr;
84
+
```
85
+
86
+
When we started using `std::array`, it was inevitable that we would encounter a C-style compatible interface. There are three ways to do this:
`std::forward_list` is a list container, and the usage is basically similar to `std::list`, so we don't spend a lot of time introducing it.
107
+
108
+
Need to know is that, unlike the implementation of the doubly linked list of `std::list`, `std::forward_list` is implemented using a singly linked list.
109
+
Provides element insertion of `O(1)` complexity, does not support fast random access (this is also a feature of linked lists),
110
+
It is also the only container in the standard library container that does not provide the `size()` method. Has a higher space utilization than `std::list` when bidirectional iteration is not required.
111
+
112
+
## 4.2 Unordered Container
113
+
114
+
We are already familiar with the ordered container `std::map`/`std::set` in traditional C++. These elements are internally implemented by red-black trees.
115
+
The average complexity of inserts and searches is `O(log(size))`. When inserting an element, the element size is compared according to the `<` operator and the element is determined to be the same.
116
+
And select the appropriate location to insert into the container. When traversing the elements in this container, the output will be traversed one by one in the order of the `<` operator.
117
+
118
+
The elements in the unordered container are not sorted, and the internals are implemented by the Hash table. The average complexity of inserting and searching for elements is `O(constant)`,
119
+
Significant performance gains can be achieved without concern for the order of the elements inside the container.
120
+
121
+
C++11 introduces two sets of unordered containers: `std::unordered_map`/`std::unordered_multimap` and
122
+
`std::unordered_set`/`std::unordered_multiset`.
123
+
124
+
Their usage is basically similar to the original `std::map`/`std::multimap`/`std::set`/`set::multiset`
125
+
Since these containers are already familiar to us, we will not compare them one by one. Let's compare `std::map` and `std::unordered_map` directly:
Another common requirement is to merge two tuples, which can be done with `std::tuple_cat`:
275
+
276
+
```cpp
277
+
auto new_tuple = std::tuple_cat(get_student(1), std::move(t));
278
+
```
279
+
280
+
You can immediately see how quickly you can traverse a tuple? But we just introduced how to index a `tuple` by a very number at runtime, then the traversal becomes simpler.
281
+
First we need to know the length of a tuple, which can:
This chapter briefly introduces the new containers in modern C++. Their usage is similar to that of the existing containers in C++. It is relatively simple, and you can choose the containers you need to use according to the actual scene, so as to get better performance.
301
+
302
+
Although `std::tuple` is effective, the standard library provides limited functionality and there is no way to meet the requirements of runtime indexing and iteration. Fortunately, we have other methods that we can implement on our own.
303
+
304
+
[Table of Content](./toc.md) | [Previous Chapter](./03-runtime.md) | [Next Chapter: Smart Pointers and Memory Management](./05-pointers.md)
0 commit comments