fix errors about 'static in previous chapters

pull/402/head
sunface 3 years ago
parent 0675bffb6b
commit 3815a650b7

@ -54,6 +54,7 @@
- [生命周期](advance/lifetime/intro.md)
- [认识生命周期](advance/lifetime/basic.md)
- [深入生命周期](advance/lifetime/advance.md)
- [&'static 和 T: 'static](advance/lifetime/static.md)
<!-- - [一些关于生命周期的误解 todo](advance/lifetime/misconceptions.md) -->
- [函数式编程](advance/functional-programing/intro.md)
- [闭包closure](advance/functional-programing/closure.md)
@ -84,6 +85,9 @@
- [实践应用多线程Web服务器 todo](advance/concurrency-with-threads/web-server.md)
- [全局变量](advance/global-variable.md)
- [错误处理](advance/errors.md)
- [Unsafe Rust doing](advance/unsafe/intro.md)
- [原生指针 doing](advance/unsafe/raw-pointer.md)
- [FFI todo](advance/unsafe/ffi.md)
<!-- - [高阶特征约束(HRTB) todo](advance/hrtb.md) -->
## 专题内容,每个专题都配套一个小型项目进行实践
@ -109,10 +113,6 @@
- [类似迭代器的Stream](tokio/stream.md))
- [优雅的关闭](tokio/graceful-shutdown.md)
- [异步跟同步共存](tokio/bridging-with-sync.md)
- [Unsafe Rust todo](unsafe/intro.md)
- [原生指针 todo](unsafe/raw-pointer.md)
- [FFI外部语言用 todo](unsafe/ffi.md)
- [对抗编译检查 doing](fight-with-compiler/intro.md)
- [幽灵数据(todo)](fight-with-compiler/phantom-data.md)

@ -532,26 +532,26 @@ Bang一个复杂的玩意儿被甩到了你面前就问怕不怕
总之,实现方法比想象中简单:加一个约束,就能暗示编译器,尽管引用吧,反正我想引用的内容比我活得久,爱咋咋地,我怎么都不会引用到无效的内容!
## 静态生命周期
在Rust中有一个非常特殊的生命周期那就是 `'static`,该生命周期意味着被它标注的引用**在编译器看来**可以和整个程序活得一样久(强烈建议再看看这句[名言](#生命周期标注语法))
在Rust中有一个非常特殊的生命周期那就是 `'static`拥有该生命周期的引用可以和整个程序活得一样久。
在之前我们学过字符串字面量,提到过它是被硬编码进 Rust 的二进制文件中,因此这些字符串变量全部具有 `'static` 的生命周期:
```rust
let s: &'static str = "我没啥优点,就是活得久,嘿嘿";
```
这时候,有些聪明的小脑瓜就开始开动了:当生命周期不知道怎么标时,标一个 `'static` 是不是很爽?这样我和编译器再也不用操心它到底活多久了。
这时候,有些聪明的小脑瓜就开始开动了:当生命周期不知道怎么标时,对类型施加一个静态生命周期的约束 `T: 'static` 是不是很爽?这样我和编译器再也不用操心它到底活多久了。
嗯,只能说,这个想法是对的,在不少情况下,标注为 `'static` 确实可以解决生命周期编译不通过的问题但是问题来了本来该引用没有活那么久但是你非要说它活那么久万一引入了潜在的BUG怎么办
嗯,只能说,这个想法是对的,在不少情况下,`'static` 约束确实可以解决生命周期编译不通过的问题但是问题来了本来该引用没有活那么久但是你非要说它活那么久万一引入了潜在的BUG怎么办
因此,遇到因为生命周期导致的编译不通过问题,首先想的应该是:是否是我们试图创建一个悬垂引用,或者是试图匹配不一致的生命周期,而不是简单粗暴的用 `'static` 来解决问题。
但是,话说回来,存在即合理,有时候,`'static` 确实可以帮助我们解决非常复杂的生命周期问题甚至是无法被手动解决的生命周期问题,那么此时就应该放心大胆的用,只要你确定:**你的所有引用的生命周期都是正确的,只是编译器太笨不懂罢了**。
总结下:
- 字符串字面量的生命周期都是 `'static`
- 当你要为某个引用标注 `'static` 时,请确保它真的活得那么久
- 实在遇到解决不了的生命周期标注问题,可以尝试 `'static`,有时候它会给你奇迹
- 生命周期 `'static` 意味着能和程序活得一样久,例如字符串字面量和特征对象
- 实在遇到解决不了的生命周期标注问题,可以尝试 `T: 'static`,有时候它会给你奇迹
> 事实上,关于 `'static`, 有两种用法: `&'static``T: 'static`,详细内容请参见[此处](https://course.rs/advance/lifetime/static.html)
## 一个复杂例子: 泛型、特征约束
手指已经疲软无力,我好想停止,但是华丽的开场都要有与之匹配的谢幕,那我们就用一个稍微复杂点的例子来结束:

@ -163,17 +163,7 @@ help: to force the async block to take ownership of `v` (and any other
先别急着给它扣帽子,虽然我有时候也想这么做。。原因是它说的是类型必须活得比 `'static` 长,而不是值。当我们说一个值是 `'static` 时,意味着它将永远存活。这个很重要,因为编译器无法知道新创建的任务将存活多久,所以唯一的办法就是让任务永远存活。
实际上编译的这个报错在告诉我们函数的参数要满足以下约束:`T: 'static`。
我们一般用 **T 被 'static 所约束** 来描述 `T: 'static`,当然你也可以说**T 类型比 `'static` 活得更久** 或 **T的值是 `'static`** ,事实上这三个是一个意思,都是说只要 `T: 'static`, 那它将永远活下去。
反而是 `&'static T` 它拥有一个不同的含义:使用`'static` 进行标注,但这个标注并不能让 `T` 永远活下去,仅仅是一个标注。
也就是说,一个类型 `T` 必须活得比 `'static` 更长,意味着它满足以下约束 `T: 'static`
PS: 这一段内容Tokio 的原文有些逻辑混乱,我已经尽可能的理清了作者想表达的含义, 同时补充了一些自己的理解,以让内容阅读起来更流畅 /
> 一个关于 `'static` 生命周期的常见误解就是它将永远存活(跟整个程序活得一样久),实际上并不是这样的。同样的,一个变量是 `'static` 并不意味着它存在内存泄漏的可能性。
如果大家对于 `'&static``T: 'static` 较为模糊,强烈建议回顾下[该章节](https://course.rs/advance/lifetime/static.html。
#### Send 约束
`tokio::spawn` 生成的任务必须实现 `Send` 特征,因为当这些任务在 `.await` 执行过程中发生阻塞时Tokio 调度器会将任务在线程间移动。

Loading…
Cancel
Save