Skip to content

Commit 9dee274

Browse files
Merge pull request #65 from zhangzhuang15/dev
Dev
2 parents 0d093e4 + 587556f commit 9dee274

23 files changed

+853
-7
lines changed

.vitepress/config.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ export default defineConfig({
174174
items: [
175175
{ text: '第一次洗牙', link: "/me/first-time/wash-teeth" },
176176
{ text: '第一次学会投篮', link: '/me/first-time/shoot' },
177-
{ text: '第一次立案', link: '/me/first-time/take-law' }
177+
{ text: '第一次立案', link: '/me/first-time/take-law' },
178+
{ text: '第一次听演唱会', link: '/me/first-time/concert'}
178179
],
179180
},
180181
],
@@ -401,6 +402,14 @@ export default defineConfig({
401402
text: 'Never Confused: Rust, Zig and Go',
402403
link: '/blog/rust-zig-go'
403404
},
405+
{
406+
text: 'Start with Zig',
407+
link: '/blog/zig',
408+
},
409+
{
410+
text: 'Tauri',
411+
link: '/blog/tauri',
412+
},
404413
{
405414
text: "博客文章阅读系列",
406415
collapsed: true,

.vitepress/theme/custom.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@
6363

6464
--home-circle-size: 3rem;
6565
--home-circle-size-half: 1.5rem;
66+
--strong-color: rgb(198, 176, 246);
67+
}
68+
69+
/* 重新定义 ** ** 包裹的文字样式 */
70+
:root .vp-doc strong {
71+
font-weight: 800;
72+
color: var(--strong-color);
6673
}
6774

6875
@media (max-width: 415px), (max-width: 320px) {

docs/blog/learning-cpp.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,8 @@ int main() {
698698
如果你没有写出对应的构造函数,C++编译器会默认提供 构造函数、拷贝构造函数、赋值运算符号,这个行为是把双刃剑,好处是省得你写一写代码,坏处是它背着你做了这些事情。因此,你最好还是明确给出这些构造函数的实现,不要空缺!
699699
:::
700700

701+
不推荐使用`A c(10, 20)` 这种初始化方式,因为它容易和函数调用或者函数定义混淆;推荐使用`A b{10, 20}` 这种方式;
702+
701703

702704
## inherit
703705
C++的继承方式提供了public, protected, private三种方式。
@@ -973,6 +975,44 @@ world
973975
调用的是Derive定义的hello, 默认参数传的是Base的
974976

975977

978+
## std::move
979+
在 Rust 语言,默认语义就是移动语义,这就意味着堆上的内存不会发生复制。但是在 c++, 它提供了拷贝构造函数和移动构造函数,语义不明确。如果实现了拷贝构造函数,就会采取值复制的语义,堆上的内存会复制。为了实现 Rust 的移动语义,必须给出移动构造函数的定义,同时使用`std::move`做类型转换,明确告知编译器,使用移动构造函数。
980+
981+
`std::move(p)` 并不会给出移动p的动作,只是将 p 的类型转化为右值类型,编译器就会调用p的移动构造函数生成一个新的同类型数据。
982+
983+
```cpp
984+
class P {
985+
public:
986+
std::string s;
987+
988+
P(P&& other) {
989+
this->s = std::move(other.s);
990+
other.s = std::string{};
991+
}
992+
}
993+
994+
void count(P&& p) {
995+
auto v = p.s.size();
996+
std::cout << v;
997+
}
998+
999+
int main() {
1000+
P p;
1001+
p.s = std::string{"hello world"};
1002+
// use P move constructor to create a new P type data as
1003+
// first arg of function count.
1004+
count(std::move(p));
1005+
return 0;
1006+
}
1007+
```
1008+
1009+
虽然 `std::move(p)` 发生了,但你仍旧可以继续使用 p ,编译器不会阻止你,因此如果没有一个良好的移动构造函数,继续使用 p 会有安全隐患。
1010+
1011+
什么时候使用`std::move`,取决于以下几点:
1012+
1. 是否要明确使用数据的移动语义。编译器会优化代码,避免调用拷贝构造函数,但这种优化不总是有效,因此你需要显式告知编译器,使用移动构造函数。
1013+
2. 数据类型是否支持移动语义。c++的标准库一般都会实现移动构造函数,你可以大胆调用`std::move`,但是数据被move之后会如何,不要冒那个风险,像Rust那样处理就好,move之后的数据永远不要去访问!
1014+
1015+
9761016
## 与现代编程特性接轨
9771017
### std::tuple
9781018
@@ -1358,4 +1398,166 @@ New way:
13581398
void hello();
13591399
```
13601400

1401+
## snippet
1402+
### Format String
1403+
```cpp
1404+
#include <format>
1405+
#include <string>
1406+
1407+
int main() {
1408+
auto s = std::string{"hello"};
1409+
auto suffix = std::string{"ts"};
1410+
auto s = std::format("{}.{}", s, suffix);
1411+
}
1412+
```
1413+
1414+
### Buff String
1415+
```cpp
1416+
#include <iostream>
1417+
#include <string>
1418+
1419+
int main() {
1420+
std::ostringstream ss;
1421+
ss << "hello";
1422+
ss << "world";
1423+
ss << 101;
1424+
ss << std::endl;
1425+
1426+
std::string s = ss.str();
1427+
}
1428+
```
1429+
1430+
### Option Value
1431+
```cpp
1432+
#include <optional>
1433+
1434+
std::optional<int> take(int v) {
1435+
if (v == -1) {
1436+
return std::nullopt;
1437+
}
1438+
return std::make_optional(v);
1439+
}
1440+
```
1441+
1442+
### Sort Vector
1443+
```cpp
1444+
#include <vector>
1445+
#include <algorithm>
1446+
#include <string>
1447+
1448+
class Case {
1449+
public:
1450+
int index;
1451+
std::string val;
1452+
1453+
Case(int i, std::string v): index(i), val(v) {}
1454+
};
1455+
1456+
int main() {
1457+
std::vector<Case> c;
1458+
c.emplace_back(1, "hello");
1459+
c.emplace_back(3, "yes");
1460+
c.emplace_back(2, "now");
1461+
1462+
std::sort(
1463+
c.cbegin(),
1464+
c.cend(),
1465+
[](Case&a, Case& b) {
1466+
return a.index < b.index;
1467+
}
1468+
);
1469+
1470+
// c is sorted from small index to big index.
1471+
}
1472+
1473+
```
1474+
1475+
### Write Vector to File
1476+
```cpp
1477+
#include <vector>
1478+
#include <unistd.h>
1479+
1480+
bool write_to_file(int fd, std::vector<uint8_t>& vector) {
1481+
auto size = 128;
1482+
auto len = vector.size();
1483+
auto ptr = vector.c_str();
1484+
1485+
while (len > 0) {
1486+
auto next_write = len > size ? size : len;
1487+
auto written = write(fd, ptr, next_write);
1488+
if (written == -1) {
1489+
return false;
1490+
}
1491+
len -= written;
1492+
ptr += written;
1493+
}
1494+
return true;
1495+
}
1496+
```
1497+
1498+
### Read File to Vector
1499+
```cpp
1500+
#include <vector>
1501+
#include <unistd.h>
1502+
#include <string.h>
1503+
1504+
bool read_file(int fd, std::vector<uint8_t>& vector) {
1505+
char buffer[128];
1506+
memset(buffer, 0, sizeof(buffer));
1507+
1508+
while (1) {
1509+
auto r = read(fd, buffer, sizeof(buffer));
1510+
if (r == 0) {
1511+
break;
1512+
}
1513+
if (r == -1) {
1514+
return false;
1515+
}
1516+
vector.insert(vector.end(), buffer, buffer + r);
1517+
}
1518+
return true;
1519+
}
1520+
```
1521+
1522+
### Thread and Mutex
1523+
```cpp
1524+
#include <thread>
1525+
#include <mutex>
1526+
#include <vector>
1527+
1528+
int main() {
1529+
std::vector<uint8_t> v;
1530+
std::mutex mtx;
1531+
1532+
auto t = std::thread{
1533+
[&](uint8_t val) {
1534+
// lock in RAII style
1535+
std::lock_guard<std::mutex> guard{ mtx };
1536+
v.push_back(val);
1537+
},
1538+
10
1539+
};
1540+
1541+
t.join();
1542+
}
1543+
```
1544+
1545+
## 使用感受
1546+
### 视频下载命令行工具
1547+
我使用cpp重构了用nodejs实现的视频下载命令行工具,收获了一些cpp的体验。
1548+
1549+
标准库不完备,要造轮子。c++的标准库没有那么全,像http网络请求就需要自己调用系统的`socket` API 实现。好处是编写代码的时候,硬逼着你与system call打交道,能提高系统编程的能力。坏处就是麻烦。
1550+
1551+
函数式不完备。js本身就提供了丰富的函数式编程语义,如`map` `reduce`,Rust也提供了。但是c++标准库提供了最基础的操作,你必须二次封装,支持更多的函数式编程语义。像`map`,c++就没有提供。
1552+
1553+
错误不好找。运行时出错,终端只会有“segment fault”之类的错误,不像Rust,可以提供更加友好的错误提示,告诉你是源码哪一行报错。为了找出cpp程序的错误,必须使用debug,在异常发生的时候,排查调用栈。
1554+
1555+
体积小。我也是使用Rust和Go编写了同样的工具,Rust花费6MB,Go花费了9MB,而c++花费了1.3MB。c++版本的实现偷了很多懒。像Go语言,自带协程调度库。像Rust实现的版本,引入了tokio运行时。这些都会导致程序体积增大,也带来了程序的可读、可维护和健壮。如果砍掉运行时,c++的1.3MB结果,一点都不出彩儿。因此,体积小,并不算是c++的亮点。
1556+
1557+
不安全。c++版本的实现,为了避免函数调用过程中,函数入参和返回值位置发生太多拷贝,使用了引用和移动。c++的编译器不会审查这些引用和移动的安全性。编写代码的时候,必须要自己小心,留意哪些资源还是有效的、存在的。说来说去,c++的所谓安全,跟c一样,还是非常依赖编程人员,即便c++提供了智能指针这种工具。
1558+
1559+
官网可读性,有待提高。你必须要到c++官网,查看标准库,才知道string,vector这些工具该怎么使用。对于类型定义的介绍,c++官网搞的非常糟糕,你根本无法从它的文字里直接明白什么意思。还好,在末尾会有一段示例代码,有的代码可读性好,一看就知道怎么用,有的代码可读性就糟糕了。它底层实现,太依赖各种模板、重载,简直就没有办法从它的代码定义中,理解到API的用法。这一点,Rust完胜。
1560+
1561+
一句话总结下,用cpp编写程序,心力憔悴,狠狠用Rust就可以了。
1562+
13611563
<Giscus />

docs/blog/programer-and-english.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,26 @@ aside: true
123123

124124
**I would expect that**, 我预期是...
125125

126-
**keep code more understandable and self-evident**, 令代码更好理解、更直观
126+
**keep code more understandable and self-evident**, 令代码更好理解、更直观
127+
128+
**break things down**, 将事情分解
129+
130+
**break problems down**, 将问题分解
131+
132+
**break things into small pieces**, 将事情拆分成零散的部分
133+
134+
**make your code adaptable**, 让你的代码更加灵活
135+
136+
**typescript adoption**, typescript的采纳
137+
138+
**how to tackle error**, 如何处理错误
139+
140+
**things become a lot easier for me**, 事情变得更加简单
141+
142+
**passion has a way of fueling your goals**, 热爱支撑你的目标
143+
144+
**do something else that is going to free up your brain**, 做点别的事情,换换脑子
145+
146+
**work out for a long time**, 花费很长时间做事
147+
148+
**step out of your house**, 到户外

docs/blog/rust-zig-go.md

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,60 @@ In conclusion, C generates 10KB-level executable file, Rust generates 100KB-leve
382382
For bare machine, C/Rust/Zig is better.
383383

384384
## CPP is Better ?
385-
In TIOBE, cpp takes up second or third spot, but it doesn't mean that cpp is better. Frankly speaking, cpp is mature, so pepole tend to adopt cpp rather than new languages, such as Rust. It feels like teachers teach you with cpp and you're more likely using cpp. If you like spending more efforts on maintaining code safety by yourself, cpp is more suitable for you.
385+
In TIOBE, cpp takes up second or third spot, but it doesn't mean that cpp is better. Frankly speaking, cpp is mature, so people tend to adopt cpp rather than new languages, such as Rust. It feels like teachers teach you with cpp and you're more likely using cpp. If you like spending more efforts on maintaining code safety by yourself, cpp is more suitable for you.
386+
387+
Linus said cpp was bullshit, it's not true. It's bullshit if you use cpp in a wrong way, and that says you have to follow code style and rules seriously. Last not but least, you can't hold safety and speed at the same time.
388+
389+
## Hello World Cmparing
390+
There're "hello world" programs written by c, cpp, zig and rust, and here are the size.
391+
392+
| language | size | compile |
393+
|:--|:--:|:--:|
394+
| c | 33KB | gcc main.c -o main |
395+
| cpp | 39KB | g++ main.cc -std=c++20 -o main |
396+
| zig(debug mode) | 861KB | zig build-exe main.zig |
397+
| rust(debug mode)| 439KB | cargo build |
398+
| zig(release-fast mode)| 50KB | zig build-ext -O ReleaseFast main.zig |
399+
| rust(release mode)| 405KB | cargo build --release |
400+
| rust(release mode and prefer dynamic)| 49KB | RUSTFLAGS="-C prefer-dynamic" cargo build --release |
401+
402+
As you can see, if we don't request safety, there is not different among these languages.
403+
404+
:::code-group
405+
```c [main.c]
406+
#include <stdio.h>
407+
int main() {
408+
printf("hello world");
409+
return 0;
410+
}
411+
```
412+
413+
```cpp [main.cc]
414+
#include <iostream>
415+
416+
int main() {
417+
std::cout << "hello world" << std::endl;
418+
return 0;
419+
}
420+
```
421+
422+
```zig [main.zig]
423+
pub fn main() !void {
424+
const std = @import("std");
425+
const stdout = std.io.getStdOut().writer();
426+
try stdout.print("Hello, World!\n", .{});
427+
}
428+
```
429+
430+
```rust [main.rs]
431+
mod util {
432+
pub fn say_hello() {
433+
println!("hello world");
434+
}
435+
};
436+
437+
fn main() {
438+
util::say_hello();
439+
}
440+
```
441+
:::

0 commit comments

Comments
 (0)