Skip to content

Commit 708f573

Browse files
feat: support ssg
1 parent ae0b737 commit 708f573

File tree

6 files changed

+213
-1
lines changed

6 files changed

+213
-1
lines changed

.github/workflows/deploy.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# 工作流名称
2+
name: 自动部署 MkDocs
3+
4+
# 触发条件:推送到 main 分支
5+
on:
6+
push:
7+
branches:
8+
- main
9+
10+
# 允许手动触发
11+
workflow_dispatch:
12+
13+
# 设置权限
14+
permissions:
15+
contents: write # 允许推送到 gh-pages 分支
16+
17+
jobs:
18+
deploy:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
# 1. 检出代码
23+
- name: 检出仓库
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0 # 获取完整历史,显示文章修改时间
27+
28+
# 2. 设置 Python
29+
- name: 设置 Python
30+
uses: actions/setup-python@v5
31+
with:
32+
python-version: "3.11"
33+
# cache: 'pip' # 缓存依赖,加速构建
34+
35+
# 3. 安装依赖
36+
- name: 安装依赖
37+
run: |
38+
pip install mkdocs-material
39+
pip install mkdocs-awesome-pages-plugin
40+
pip install mkdocs-git-revision-date-localized-plugin
41+
42+
# 4. 构建网站
43+
- name: 构建网站
44+
run: mkdocs build --clean
45+
46+
# 5. 自动部署到 gh-pages 分支(这一步会自动触发 GitHub Pages)
47+
- name: 部署到 GitHub Pages
48+
uses: peaceiris/actions-gh-pages@v4
49+
with:
50+
github_token: ${{ secrets.GITHUB_TOKEN }} # GitHub 自动提供的 token
51+
publish_dir: ./site # MkDocs 构建输出目录

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
> codes_and_assets下放置着本教程所有的代码, 或硬件电路图或者是PCB文件等
1212
> 具体的细节,请到[具体的说明步骤🖱](./codes_and_assets/instractions.md)
1313
> tutorial下放置着教程的Markdown文件, 您可以使用其他Markdown浏览器阅读这些教程
14-
> 您如果不知道从何开始,请到[从这里开始!🖱](./tutorial/README.md)查看!
14+
> 您如果不知道从何开始,请到[从这里开始!🖱](./tutorial/index.md)查看!
1515
1616
## 这是什么?
1717

tutorial/Awesome-Embedded.ico

4.19 KB
Binary file not shown.

tutorial/Awesome-Embedded.png

1.34 MB
Loading
File renamed without changes.

tutorial/改进我们的split.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# 现代C++工程实践:简单的IniParser3——改进我们的split
2+
3+
## 前言
4+
5+
上一篇博客我们提到了说我们是要改进咱们的split的,传送门在下面:
6+
7+
- CSDN:[现代C++工程实践:简单的IniParser2:分解需求与编写split-CSDN博客](https://blog.csdn.net/charlie114514191/article/details/155731063)
8+
- 知乎:[现代C++工程实践:简单的IniParser2:分解需求与编写split - 老老老陈醋的文章 - 知乎](https://zhuanlan.zhihu.com/p/1981659758034437080)
9+
- Github: [Awesome-Embedded-Learning-Studio/Tutorial_cpp_SimpleIniParser: 这是我们C++工程化开始的旅程!手搓一个最简单的Ini分析器!This is the beginning of our journey in C++ engineering! Handcrafting the simplest INI parser!](https://github.com/Awesome-Embedded-Learning-Studio/Tutorial_cpp_SimpleIniParser)
10+
11+
笔者这里单独开了一个博客全面的介绍了`std::string_view`
12+
13+
- [简说C++17新东西:string_view-CSDN博客](https://blog.csdn.net/charlie114514191/article/details/155843231)
14+
- [C++17: std::string_view 全攻略 - 老老老陈醋的文章 - 知乎](https://zhuanlan.zhihu.com/p/1982745462256714113)
15+
16+
看这篇博客之前,单独看看string_view。
17+
18+
## 下面这个改进对吗
19+
20+
下面这个片段是笔者一开始写出来的,各位看官阅读一下:
21+
22+
```cpp
23+
std::vector<std::string_view> splits_v2(
24+
const std::string& src, const char ch) {
25+
26+
std::vector<std::string_view> results;
27+
28+
if (src.empty()) {
29+
return results;
30+
}
31+
32+
auto current_positions = src.find(ch, 0);
33+
const size_t str_sz = src.size();
34+
size_t last_index = 0;
35+
36+
while (current_positions != std::string::npos) {
37+
results.emplace_back(src.substr(last_index, current_positions - last_index));
38+
results.emplace_back(src.substr(current_positions, 1));
39+
40+
last_index = current_positions + 1;
41+
current_positions = src.find(ch, current_positions + 1);
42+
}
43+
44+
results.emplace_back(src.substr(last_index));
45+
return results;
46+
}
47+
```
48+
49+
看出来问题了吗?
50+
51+
#### 关键问题: `substr()` 返回的是新的 `std::string`
52+
53+
`std::string::substr()` 不是返回视图,它是 **拷贝构造一个新的字符串**:
54+
55+
```cpp
56+
std::string substr(pos, count);
57+
```
58+
59+
而你的函数返回的是:
60+
61+
```cpp
62+
std::vector<std::string_view>
63+
```
64+
65+
意味着如下情况会发生:
66+
67+
1. `src.substr(...)` 创建了一个**临时的 std::string 对象**
68+
2. `string_view` 绑定到临时对象的内部 `buffer`
69+
3. 临时对象生命周期仅存活到当前表达式结束
70+
4. `string_view` 中的 `ptr` 立即悬空(dangling pointer)
71+
5. 返回后访问 view → **UB(未定义行为)直接爆炸**
72+
73+
也就是说,这个函数看起来运行正常,但返回的数据其实**全部悬空**。所以笔者在Release模式下就惊喜的发现了一堆bug:包括随机数据和直接悬空的问题
74+
75+
这是一种非常常见的 “**临时对象挂掉,string_view 变尸体**” 的经典错误。
76+
77+
------
78+
79+
## 第二版:问题是如何被修复的?
80+
81+
来看修复后的版本:
82+
83+
```cpp
84+
std::vector<std::string_view> splits_v2_fixed(
85+
const std::string& src, const char ch) {
86+
87+
std::vector<std::string_view> results;
88+
if (src.empty()) {
89+
return results;
90+
}
91+
92+
std::string_view src_view(src); // ⭐ 关键修复点:构造一个稳定的 view
93+
94+
const size_t delim_count = std::count(src.begin(), src.end(), ch);
95+
results.reserve(delim_count * 2 + 1);
96+
97+
size_t last_index = 0;
98+
size_t current_positions = src.find(ch, last_index);
99+
100+
while (current_positions != std::string::npos) {
101+
102+
results.emplace_back(
103+
src_view.substr(last_index, current_positions - last_index));
104+
105+
results.emplace_back(
106+
src_view.substr(current_positions, 1));
107+
108+
last_index = current_positions + 1;
109+
current_positions = src.find(ch, last_index);
110+
}
111+
112+
results.emplace_back(src_view.substr(last_index));
113+
114+
return results;
115+
}
116+
```
117+
118+
#### 修复的核心点:使用原始 `src` 构造 `string_view` 作为根
119+
120+
```cpp
121+
std::string_view src_view(src);
122+
```
123+
124+
这样带来两个关键改进:
125+
126+
##### **1. substr() 变成了 `"视图切片"`,不是 `"创建副本"`**
127+
128+
`string_view::substr()` 的实现机制:
129+
130+
- 不会创建新的字符串
131+
- 只计算新的 offset + length
132+
- 返回的 `string_view` 始终指向原始 `src` 的内存区域
133+
134+
源码层面类似:
135+
136+
```cpp
137+
return string_view(this->data() + pos, count);
138+
```
139+
140+
你再怎么分割,它都只是“原文的一块切片”,不会发生内存复制,也不会有临时对象。
141+
142+
##### **2. 原始 `src` 在整个函数调用外都是稳定对象**
143+
144+
你传进来的是:
145+
146+
```cpp
147+
const std::string& src
148+
```
149+
150+
只要调用者保证 `src` 的生命周期≥返回的 vector 的使用生命周期,那么:
151+
152+
- 所有 view 保证不悬空
153+
- 性能更高(完全无拷贝)
154+
- 内存占用更小
155+
156+
现在这个split就被改进了!我们马上就能跑步进入编写一个真正的split了!
157+
158+
159+
160+
161+

0 commit comments

Comments
 (0)