Skip to content

Commit ee30575

Browse files
committed
book: add C++17 std::string_view and std::byte
New section 4.4 introduces the non-owning read-only std::string_view (with a lifetime caveat) and the non-arithmetic std::byte raw-memory type. Compiled examples in code/4/4.4 and code/4/4.5. Refs changkun#1
1 parent 371bd68 commit ee30575

4 files changed

Lines changed: 120 additions & 0 deletions

File tree

‎book/en-us/04-containers.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,41 @@ The call site is then very straightforward, and no runtime indexing is needed be
326326
iterate_tuple([](const auto& v) { std::cout << v << ' '; }, new_tuple);
327327
```
328328
329+
## 4.4 `std::string_view` and `std::byte`
330+
331+
### `std::string_view`
332+
333+
`std::string_view`, introduced in C++17, is a **non-owning, read-only** view over a sequence of characters; it holds just a pointer and a length. Declaring a parameter as `std::string_view` accepts both a `std::string` and a string literal, **without any copy or allocation**:
334+
335+
```cpp
336+
#include <string_view>
337+
338+
void print(std::string_view sv) {
339+
std::cout << sv << " (size = " << sv.size() << ")" << std::endl;
340+
}
341+
342+
std::string_view sv = "hello, world";
343+
print(sv.substr(0, 5)); // "hello"; substr does not allocate
344+
345+
std::string s = "from std::string";
346+
print(s); // implicit conversion, no copy
347+
```
348+
349+
Mind its **lifetime**: a `string_view` does not own the underlying data, so the referenced character sequence must outlive the view, otherwise you get a dangling reference.
350+
351+
### `std::byte`
352+
353+
`std::byte` represents a single byte of **raw memory**. Unlike `char` or `unsigned char`, it is not an arithmetic type — the standard defines only bitwise operators for it, which prevents accidental arithmetic on raw bytes at the type level:
354+
355+
```cpp
356+
#include <cstddef>
357+
358+
std::byte b{0b0000'1100}; // 12
359+
b <<= 2; // 48
360+
b |= std::byte{0b0000'0001}; // 49
361+
int v = std::to_integer<int>(b); // explicit conversion to an integer: 49
362+
```
363+
329364
## Conclusion
330365
331366
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, to get better performance.

‎book/zh-cn/04-containers.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,41 @@ void iterate_tuple(Func f, const std::tuple<Args...>& tpl) {
326326
iterate_tuple([](const auto& v) { std::cout << v << ' '; }, new_tuple);
327327
```
328328
329+
## 4.4 `std::string_view` 与 `std::byte`
330+
331+
### `std::string_view`
332+
333+
C++17 引入的 `std::string_view` 是对一段字符序列的**非拥有 (non-owning)、只读**视图,它仅保存一个指针和一个长度。把函数形参写成 `std::string_view` 既可以接受 `std::string`,也可以接受字符串字面量,而且**不会发生任何拷贝或内存分配**:
334+
335+
```cpp
336+
#include <string_view>
337+
338+
void print(std::string_view sv) {
339+
std::cout << sv << " (size = " << sv.size() << ")" << std::endl;
340+
}
341+
342+
std::string_view sv = "hello, world";
343+
print(sv.substr(0, 5)); // "hello",substr 不分配内存
344+
345+
std::string s = "from std::string";
346+
print(s); // 隐式转换,无拷贝
347+
```
348+
349+
需要特别注意其**生命周期**:`string_view` 不拥有底层数据,因此必须保证被引用的字符序列在视图存活期间一直有效,否则会产生悬垂引用。
350+
351+
### `std::byte`
352+
353+
`std::byte` 用于表示一段**原始内存**中的一个字节。与 `char` 或 `unsigned char` 不同,它不是算术类型——标准只为其定义了位运算符,从而在类型层面避免了对原始字节进行意外的算术运算:
354+
355+
```cpp
356+
#include <cstddef>
357+
358+
std::byte b{0b0000'1100}; // 12
359+
b <<= 2; // 48
360+
b |= std::byte{0b0000'0001}; // 49
361+
int v = std::to_integer<int>(b); // 需要显式转换为整数:49
362+
```
363+
329364
## 总结
330365
331366
本章简单介绍了现代 C++ 中新增的容器,它们的用法和传统 C++ 中已有的容器类似,相对简单,可以根据实际场景丰富的选择需要使用的容器,从而获得更好的性能。

‎code/4/4.4.string.view.cpp‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// 4.4.string.view.cpp
3+
// chapter 04 containers
4+
// modern c++ tutorial
5+
//
6+
// created by changkun at changkun.de
7+
// https://github.com/changkun/modern-cpp-tutorial
8+
//
9+
10+
#include <iostream>
11+
#include <string>
12+
#include <string_view>
13+
14+
// std::string_view is a non-owning, read-only view over a character
15+
// sequence; passing it avoids copying and accepts both std::string and
16+
// string literals.
17+
void print(std::string_view sv) {
18+
std::cout << sv << " (size = " << sv.size() << ")" << std::endl;
19+
}
20+
21+
int main() {
22+
std::string_view sv = "hello, world";
23+
print(sv.substr(0, 5)); // "hello", no allocation
24+
25+
std::string s = "from std::string";
26+
print(s); // implicit conversion, no copy
27+
28+
print("from a literal");
29+
}

‎code/4/4.5.byte.cpp‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// 4.5.byte.cpp
3+
// chapter 04 containers
4+
// modern c++ tutorial
5+
//
6+
// created by changkun at changkun.de
7+
// https://github.com/changkun/modern-cpp-tutorial
8+
//
9+
10+
#include <cstddef>
11+
#include <iostream>
12+
13+
// std::byte (C++17) represents a byte of raw memory. Unlike char or
14+
// unsigned char, it is not an arithmetic type: only bitwise operators
15+
// are defined, which prevents accidental arithmetic on raw bytes.
16+
int main() {
17+
std::byte b{0b0000'1100}; // 12
18+
b <<= 2; // 48
19+
b |= std::byte{0b0000'0001};
20+
std::cout << std::to_integer<int>(b) << std::endl; // 49
21+
}

0 commit comments

Comments
 (0)