Skip to content

Commit 84b86e1

Browse files
committed
fix: 🐛 update package
1 parent a793a2b commit 84b86e1

File tree

6 files changed

+56
-206
lines changed

6 files changed

+56
-206
lines changed

.vitepress/config.mts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ export default defineConfig({
2727
outDir: OUT_DIR,
2828
base: BASE_PATH,
2929
vite: {
30+
ssr: {
31+
noExternal: [
32+
'@ver5/vitepress-plugin-link-preview',
33+
'@ver5/vitepress-plugin-rust-playground'
34+
]
35+
},
3036
resolve: {
3137
alias: {
3238
"@vp": resolve(__dirname),
@@ -58,15 +64,15 @@ export default defineConfig({
5864
config(md) {
5965
md
6066
.use<rustPlaygroundOptions>(rustPlaygroundPlugin)
67+
.use<ImageOptions>(imagePlugin)
6168
.use(markIt)
6269
.use(alignPlugin)
6370
.use<InternalLinkOptions>(internalLinkPlugin, {
6471
sidebar: books,
6572
base: BASE_PATH,
6673
rules: link_plugin_rules
6774
})
68-
.use<ImageOptions>(imagePlugin)
69-
.use(InlineLinkPreviewElementTransform);
75+
.use(InlineLinkPreviewElementTransform)
7076
},
7177
},
7278
themeConfig: {

docs/第 23 章 动态分派和静态分派/23.1 trait object.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# 23.1 trait object
22

3-
什么是 trait object 呢?指向 trait 的指针就是 trait object。假如 Bird 是一个 trait 的名称,那么 `dyn Bird` 就是一个 DST 动态大小类型。`&dyn Bird``&mut dyn Bird``Box<dyn Bird>``*const dyn Bird``*mut dyn Bird`以及`Rc<dyn Bird>`等等都是 Trait Object。
3+
什么是 trait object 呢?指向 trait 的指针就是 trait object。
4+
假如 `Bird` 是一个 trait 的名称,那么 `dyn Bird` 就是一个 DST 动态大小类型。`&dyn Bird``&mut dyn Bird``Box<dyn Bird>``*const dyn Bird``*mut dyn Bird` 以及 `Rc<dyn Bird>` 等等都是 Trait Object。
45

56
示例:
7+
68
```rust
79
use std::fmt::Debug;
810

@@ -33,12 +35,11 @@ fn main() {
3335

3436
示例代码中,`dyn_trait``impl_trait` 是两个函数,它们都返回实现了 Debug trait 的类型。
3537

36-
`dyn_trait` 返回一个 Box 指针,指向动态分发的类型,而 `impl_trait` 直接返回一个实现了 Debug 的类型(在这里是 u8 和字符串类型)。
38+
`dyn_trait` 返回一个 Box 指针,指向动态分发的类型,而 `impl_trait` 直接返回一个实现了 Debug 的类型(在这里是 `u8` 和字符串类型)。
3739
这意味着 `dyn_trait` 可以存储不同的类型,并在运行时动态调用其 Debug 实现,而 `impl_trait` 只能返回固定的类型(在这里是字符串类型)。
3840

39-
-----
40-
41-
当指针指向 trait 的时候,这个指针就不是一个普通的指针了,变成一个“胖指针”。请大家回忆一下前文所讲解的 DST 类型:数组类型`[T]`是一个 DST 类型,因为它的大小在编译阶段是不确定的,相对应的,`&[T]`类型就是一个“胖指针”,它不仅包含了指针指向数组的其中一个元素,同时包含一个长度信息。它的内部表示实质上是 Slice 类型。
41+
当指针指向 trait 的时候,这个指针就不是一个普通的指针了,变成一个“胖指针”。
42+
请大家回忆一下前文所讲解的 DST 类型:数组类型`[T]`是一个 DST 类型,因为它的大小在编译阶段是不确定的,相对应的,`&[T]`类型就是一个“胖指针”,它不仅包含了指针指向数组的其中一个元素,同时包含一个长度信息。它的内部表示实质上是 Slice 类型。
4243

4344
同理,Bird 只是一个 trait 的名字,符合这个 trait 的具体类型可能有多种,这些类型并不具备同样的大小,因此使用 `dyn Bird` 来表示满足 Bird 约束的 DST 类型。指向 DST 的指针理所当然也应该是一个“胖指针”,它的名字就叫 trait object。比如`Box<dyn Bird>`,它的内部表示可以理解成下面这样:
4445

@@ -100,7 +101,7 @@ fn main() {
100101

101102
执行结果为:
102103

103-
```rust
104+
```
104105
Size of p_duck 8, Size of p_bird 16
105106
Duck::fly 139997348684016
106107
Swan::fly 139997348684320
@@ -111,7 +112,8 @@ data in vtable [139997348687008, 0, 1, 139997348684320]
111112
```
112113

113114
我们可以看到,直接针对对象取指针,得到的是普通指针,它占据 64 bit 的空间。
114-
如果我们把这个指针使用 as 运算符转换为 trait object,它就成了胖指针,携带了额外的信息。这个额外信息很重要,因为我们还需要使用这个指针调用函数。如果指向 trait 的指针只包含了对象的地址,那么它就没办法实现针对不同的具体类型调用不同的函数了。所以,它不仅要包含一个指向真实对象的指针,还要有一个指向所谓的“虚函数表”的指针。
115+
如果我们把这个指针使用 `as` 运算符转换为 trait object,它就成了胖指针,携带了额外的信息。这个额外信息很重要,因为我们还需要使用这个指针调用函数。如果指向 trait 的指针只包含了对象的地址,那么它就没办法实现针对不同的具体类型调用不同的函数了。
116+
所以,它不仅要包含一个指向真实对象的指针,还要有一个指向所谓的“虚函数表”的指针。
115117
我们把虚函数表里面的内容打印出来可以看到,里面有我们需要被调用的具体函数的地址。
116118

117119
从这里的分析结果可以看到,Rust 的动态分派和 C++ 的动态分派,内存布局有所不同。在 C++ 里,如果一个类型里面有虚函数,那么每一个这种类型的变量内部都包含一个指向虚函数表的地址。
Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# 4.3 main 函数
22

3-
在大部分主流操作系统上,一个进程开始执行的时候可以接受一系列的参数,退出的时候也可以返回一个错误码。许多编程语言也因此为 main 函数设计了参数和返回值类型。以 C 语言为例,主函数的原型一般允许定义成以下几种形式:
4-
5-
---
3+
在大部分主流操作系统上,一个进程开始执行的时候可以接受一系列的参数,退出的时候也可以返回一个错误码。许多编程语言也因此为 `main` 函数设计了参数和返回值类型。以 C 语言为例,主函数的原型一般允许定义成以下几种形式:
64

75
```rust
86
int main(void);
@@ -13,12 +11,8 @@ int main(int argc, char *argv[]);
1311
int main(int argc, char **argv, char **env);
1412
```
1513

16-
---
17-
1814
Rust 的设计稍微有点不一样,传递参数和返回状态码都由单独的 API 来完成,示例如下:
1915

20-
---
21-
2216
```rust
2317
fn main() {
2418
for arg in std::env::args() {
@@ -29,13 +23,9 @@ fn main() {
2923
}
3024
```
3125

32-
---
33-
3426
编译,执行并携带几个参数,可以看到:
3527

36-
---
37-
38-
```rust
28+
```sh
3929
$ test -opt1 opt2 -- opt3
4030
Arg: test
4131
Arg: -opt1
@@ -44,13 +34,9 @@ Arg: --
4434
Arg: opt3
4535
```
4636

47-
---
48-
49-
每个被空格分开的字符串都是一个参数。进程可以在任何时候调用 exit()直接退出,退出时候的错误码由 exit()函数的参数指定。
37+
每个被空格分开的字符串都是一个参数。进程可以在任何时候调用 `exit()` 直接退出,退出时候的错误码由 `exit()` 函数的参数指定。
5038

51-
如果要读取环境变量,可以用 std::env::var()以及 std::env::vars()函数获得。示例如下:
52-
53-
---
39+
如果要读取环境变量,可以用 `std::env::var()` 以及 `std::env::vars()` 函数获得。示例如下:
5440

5541
```rust
5642
fn main() {
@@ -65,8 +51,7 @@ fn main() {
6551
}
6652
```
6753

68-
---
69-
70-
`var()`函数可以接受一个字符串类型参数,用于查找当前环境变量中是否存在这个名字的环境变量,`vars()`函数不携带参数,可以返回所有的环境变量。
54+
`var()` 函数可以接受一个字符串类型参数,用于查找当前环境变量中是否存在这个名字的环境变量,`vars()` 函数不携带参数,可以返回所有的环境变量。
7155

72-
此前,Rust 的`main`函数只支持无参数、无返回值类型的声明方式,即`main`函数的签名固定为:`fn main() -> ()`。但是,在引入了`?`符号作为错误处理语法糖之后,就变得不那么优雅了,因为`?`符号要求当前所在的函数返回的是 Result 类型,这样一来,问号就无法直接在`main`函数中使用了。为了解决这个问题,Rust 设计组扩展了`main`函数的签名,使它变成了一个泛型函数,这个函数的返回类型可以是任何一个满足 Termination trait 约束的类型,比如`()``Result<(), E>`等类型就是满足这个约束的,它们都可以作为`main`函数的返回类型。关于这个问题,可以参见第 33 章。
56+
此前,Rust 的 `main` 函数只支持无参数、无返回值类型的声明方式,即 `main` 函数的签名固定为:`fn main() -> ()`。但是,在引入了 `?` 符号作为错误处理语法糖之后,就变得不那么优雅了,因为 `?` 符号要求当前所在的函数返回的是 Result 类型,这样一来,问号就无法直接在 `main` 函数中使用了。
57+
为了解决这个问题,Rust 设计组扩展了 `main` 函数的签名,使它变成了一个泛型函数,这个函数的返回类型可以是任何一个满足 Termination trait 约束的类型,比如 `()``Result<(), E>` 等类型就是满足这个约束的,它们都可以作为`main`函数的返回类型。关于这个问题,可以参见第 33 章。

docs/第 4 章 函数/4.4 const fn.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
1-
# 4.4 const fn
1+
# 4.4 `const fn`
22

3-
函数可以用 const 关键字修饰,这样的函数**在编译阶段被编译器执行,返回值也会作为常量进入程序的代码中**
3+
函数可以用 `const` 关键字修饰,这样的函数**在编译阶段被编译器执行,返回值也会作为常量进入程序的代码中**
44

5-
const fn 的主要用途有以下几个方面:
5+
`const fn` 的主要用途有以下几个方面:
66

7-
1. 在编译时计算常量表达式:const fn 可以用来在编译时计算常量表达式。由于这类函数的返回值是常量,所以可以在编译时就直接将其值嵌入到代码中,从而提高代码的执行效率。
7+
1. 在编译时计算常量表达式:`const fn` 可以用来在编译时计算常量表达式。由于这类函数的返回值是常量,所以可以在编译时就直接将其值嵌入到代码中,从而提高代码的执行效率。
88
示例如下:
99
```rust
10-
const fn cube(num: usize) -> usize {
11-
num * num * num
12-
}
10+
const fn cube(num: usize) -> usize {
11+
num * num * num
12+
}
1313

14-
fn main() {
15-
const DIM : usize = cube(2);
16-
const ARR : [i32; DIM] = [0; DIM];
14+
fn main() {
15+
const DIM : usize = cube(2);
16+
const ARR : [i32; DIM] = [0; DIM];
1717

18-
println!("{:?}", ARR);
19-
}
18+
println!("{:?}", ARR);
19+
}
2020
```
2121

22-
`cube`函数接受数字参数,它会返回一个数字,而且这个返回值本身可以用于给一个 const 常量做初始化,const 常量又可以当成一个常量数组的长度使用。
22+
`cube` 函数接受数字参数,它会返回一个数字,而且这个返回值本身可以用于给一个 `const` 常量做初始化,`const` 常量又可以当成一个常量数组的长度使用。
2323

24-
2. 对比与宏的优劣:和宏一样,const fn 可以接受参数并进行计算,但与宏不同的是,const fn 无需使用反射技术,因此编译器能够保证 const fn 的类型安全性和性能。
24+
2. 对比与宏的优劣:和宏一样,`const fn` 可以接受参数并进行计算,但与宏不同的是,`const fn` 无需使用反射技术,因此编译器能够保证 `const fn` 的类型安全性和性能。
2525

26-
3. 常量泛型:使用 const fn 可以定义常量泛型,这对一些需要固定值的场景非常有用。使用 const_fn 定义常量泛型可以提高代码的复用性和可读性。
26+
3. 常量泛型:使用 `const fn` 可以定义常量泛型,这对一些需要固定值的场景非常有用。使用 `const fn` 定义常量泛型可以提高代码的复用性和可读性。
2727
```rust
28-
const fn square<T: Into<i32>>(input: T) -> i32 {
29-
let x = input.into();
30-
x * x
31-
}
28+
const fn square<T: Into<i32>>(input: T) -> i32 {
29+
let x = input.into();
30+
x * x
31+
}
3232

33-
const SQUARE_OF_3: i32 = square(3);
34-
const SQUARE_OF_4: i32 = square(4);
33+
const SQUARE_OF_3: i32 = square(3);
34+
const SQUARE_OF_4: i32 = square(4);
3535
```
3636

37-
const fn 中使用`if`、`if let``match`,这有助于在 const fn 中使用条件语句:
37+
`const fn` 中使用 `if`、`if let``match`,这有助于在 `const fn` 中使用条件语句:
3838

3939
```rust
4040
// Use of if statement in const function.
@@ -64,6 +64,6 @@ fn main() {
6464
}
6565
```
6666

67-
还可以在 const fn 中使用 whilewhile let 和 loop 循环、使用`&&``||`操作符等。
67+
还可以在 `const fn` 中使用 `while``while let``loop` 循环、使用 `&&``||` 操作符等。
6868

69-
总之,const fn 是 Rust 语言中的一个非常实用的特性,能够在编译期提升代码效率和安全性。
69+
总之,`const fn` 是 Rust 语言中的一个非常实用的特性,能够在编译期提升代码效率和安全性。

package.json

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@
66
"docs:preview": "vitepress preview"
77
},
88
"devDependencies": {
9-
"@codemirror/lang-rust": "^6.0.1",
10-
"@codemirror/theme-one-dark": "^6.1.2",
119
"@nolebase/vitepress-plugin-enhanced-mark": "^2.2.0",
12-
"@nolebase/vitepress-plugin-inline-link-preview": "^2.2.0",
13-
"@types/markdown-it": "^14.1.1",
14-
"@types/markdown-it-container": "^2.0.5",
10+
"@types/markdown-it": "^14.1.2",
1511
"@types/node": "^20.2.3",
1612
"@ver5/markdown-it-align": "^1.0.0",
1713
"@ver5/markdown-it-image": "^1.0.0",
@@ -21,13 +17,10 @@
2117
"@ver5/vitepress-plugin-search": "^1.0.7",
2218
"@ver5/vitepress-plugin-sidebar": "^1.0.0",
2319
"@vueuse/core": "^10.1.2",
24-
"flexsearch": "^0.7.31",
2520
"markdown-it-container": "^3.0.0",
2621
"markdown-it-mark": "^3.0.1",
2722
"sass": "^1.62.1",
2823
"tslib": "^2.5.2",
29-
"vite": "^5.2.6",
30-
"vitepress": "^1.2.3",
31-
"vue": "^3.3.4"
24+
"vitepress": "^1.5.0"
3225
}
3326
}

0 commit comments

Comments
 (0)