Skip to content

Commit b522dac

Browse files
committed
feat: improve the code sample for std::inplace_vector
1 parent 7b51038 commit b522dac

1 file changed

Lines changed: 18 additions & 6 deletions

File tree

documents/vol3-standard-library/10-new-containers-cpp23-26.md

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,32 @@ int main()
6666

6767
第二个是 `std::inplace_vector<T, N>`,C++26 进的标准(提案 P0843)。它填的是 `array``vector` 中间的缝:`array<T, N>` 大小编译期定死、不能变;`vector<T>` 能变长但要堆分配(扩容时 new 新块、拷贝、释放旧块)。很多时候你要的是「容量上限编译期知道、运行期 size 可变、但绝不碰堆」——`inplace_vector` 就是干这个的。它的元素**直接存在对象内部**(对象本身占 `sizeof(T) * N` 那块空间,放栈上或静态区),运行期可以在 0 到 N 之间增删,不 new、不扩容、不拷贝搬移。
6868

69-
最讨喜的一个性质是:**`T` 是 trivially copyable 时,`inplace_vector<T, N>` 本身也是 trivially copyable**。这意味着它可以整体 `memcpy`、可以放进寄存器、可以安全交给 DMA——这些对嵌入式和系统编程极重要,[array 深入](02-array.md) 讲过的「连续内存 + trivially copyable」红利,inplace_vector 同样吃到,而 `std::vector` 因为持有一个堆指针、不是 trivially copyable,是吃不到的。容量超限时的行为也设计得克制:`push_back` 超过 N 会抛 `std::bad_alloc`(异常关闭时退化为 terminate),而想避免异常可以用 C++26 的 `try_push_back`/`try_emplace_back`,它们超限时不抛、返回一个错误指示,适合 `-fno-exceptions` 环境。
69+
最讨喜的一个性质是:**`T` 是 trivially copyable 时,`inplace_vector<T, N>` 本身也是 trivially copyable**。这意味着它可以整体 `memcpy`、可以放进寄存器、可以安全交给 DMA——这些对嵌入式和系统编程极重要,[array 深入](02-array.md) 讲过的「连续内存 + trivially copyable」红利,inplace_vector 同样吃到,而 `std::vector` 因为持有一个堆指针、不是 trivially copyable,是吃不到的。容量超限时的行为也设计得克制:`push_back` 超过 N 会抛 `std::bad_alloc`(异常关闭时退化为 terminate),而想避免异常可以用 C++26 的 `try_push_back`/`try_emplace_back`,它们超限时不抛、返回类型是std::optional<T&>, 空值来代表失败,适合 `-fno-exceptions` 环境。
7070

7171
```cpp
7272
#include <cstdio>
7373
#include <inplace_vector>
74+
#include <type_traits>
7475

7576
int main()
7677
{
7778
std::inplace_vector<int, 4> v; // 容量上限 4,绝不堆分配
79+
static_assert(std::is_trivially_copyable_v<decltype(v)::value_type>); // 由于存储类型int是trivially copyable
80+
static_assert(std::is_trivially_copyable_v<decltype(v)>); // 整个inplace_vector都会是trivially copyable
81+
7882
v.push_back(1);
7983
v.push_back(2);
80-
v.push_back(3); // size 现在 3,还能再塞一个
81-
std::printf("size = %zu, capacity = %zu\n", v.size(), v.capacity());
82-
// 再 push 到满:v.push_back(4) 成功;v.push_back(5) 超容量,抛 bad_alloc
83-
// 想避免异常用 try_push_back / try_emplace_back——超限不抛,返回失败指示
84+
v.push_back(3);
85+
v.push_back(4); // size 现在 4,无法再塞了
86+
std::printf("size = %zu, max_size = %zu, capacity = %zu\n", v.size(), v.max_size(), v.capacity());
87+
// 此时如果 v.push_back(5) 超容量,抛 bad_alloc
88+
// 想避免异常用 try_push_back / try_emplace_back——超限不抛,返回std::optional<T&>, 空值来代表失败
89+
std::optional<int&> res = v.try_push_back(5);
90+
if (res.has_value()) {
91+
std::printf("successfully pushed the fifth element %d", res.value());
92+
} else {
93+
std::printf("failed to push the fifth element due to out of fixed capacity");
94+
}
8495
return 0;
8596
}
8697
```
@@ -90,7 +101,8 @@ g++ -std=c++26 -O2 -o /tmp/ipv_demo /tmp/ipv_demo.cpp && /tmp/ipv_demo
90101
```
91102

92103
```text
93-
size = 3, capacity = 4
104+
size = 4, max_size = 4, capacity = 4
105+
failed to push the fifth element due to out of fixed capacity
94106
```
95107

96108
`inplace_vector``array` 的边界要拎清:`array<T, N>` 的 size 恒等于 N,是定长;`inplace_vector<T, N>` 的容量上限是 N,但 size 在 0 到 N 之间运行期可变。要定长用 array,要「上限已知 + 运行期可变 + 不堆分配」用 inplace_vector。

0 commit comments

Comments
 (0)