diff --git a/ChangeLog.md b/ChangeLog.md index e5fbdad..d65c195 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,7 +4,7 @@ - Add [Zh - Formating] - Add [Zh - Lifetime-Basic] - +- Add [Zh - Static] ## 2022-03-31 diff --git a/zh-CN/src/SUMMARY.md b/zh-CN/src/SUMMARY.md index 815c040..0066614 100644 --- a/zh-CN/src/SUMMARY.md +++ b/zh-CN/src/SUMMARY.md @@ -46,7 +46,7 @@ - [使用use引入模块及受限可见性](crate-module/use-pub.md) - [注释和文档](comments-docs.md) - [格式化输出](formatted-output.md) -- [生命周期 todo](lifetime/intro.md) +- [生命周期](lifetime/intro.md) - [生命周期基础](lifetime/basic.md) - [&'static 和 T: 'static](lifetime/static.md) - [深入生命周期](lifetime/advance.md) diff --git a/zh-CN/src/lifetime/static.md b/zh-CN/src/lifetime/static.md index 782446e..18c2b50 100644 --- a/zh-CN/src/lifetime/static.md +++ b/zh-CN/src/lifetime/static.md @@ -1,5 +1,143 @@ # &'static and T: 'static +`'static` 是一个 Rust 保留的生命周期名称,在之前我们可能已经见过好几次了: +```rust +// 引用的生命周期是 'static : +let s: &'static str = "hello world"; +// 'static 也可以用于特征约束中: +fn generic(x: T) where T: 'static {} +``` + +虽然它们都是 `'static`,但是也稍有不同。 + +## &'static +作为一个引用生命周期,`&'static` 说明该引用指向的数据可以跟程序活得一样久,但是该引用的生命周期依然有可能被强转为一个更短的生命周期。 + +1、🌟🌟 有好几种方法可以将一个变量标记为 `'static` 生命周期, 其中两种都是和保存在二进制文件中相关( 例如字符串字面量就是保存在二进制文件中,它的生命周期是 `'statci` )。 + +```rust,editable + +/* 使用两种方法填空 */ +fn main() { + __; + need_static(v); + + println!("Success!") +} + +fn need_static(r : &'static str) { + assert_eq!(r, "hello"); +} +``` + +2、 🌟🌟🌟🌟 使用 `Box::leak` 也可以产生 `'static` 生命周期 +```rust,editable +#[derive(Debug)] +struct Config { + a: String, + b: String, +} +static mut config: Option<&mut Config> = None; + +/* 让代码工作,但不要修改函数的签名 */ +fn init() -> Option<&'static mut Config> { + Some(&mut Config { + a: "A".to_string(), + b: "B".to_string(), + }) +} + + +fn main() { + unsafe { + config = init(); + + println!("{:?}",config) + } +} +``` + +3、 🌟 `&'static` 只能说明引用指向的数据是能一直存活的,但是引用本身依然受限于它的作用域 +```rust,editable +fn main() { + { + // 字符串字面量能跟程序活得一样久,因此 `static_string` 的生命周期是 `'static` + let static_string = "I'm in read-only memory"; + println!("static_string: {}", static_string); + + // 当 `static_string` 超出作用域时,该引用就无法再被使用,但是引用指向的数据( 字符串字面量 ) 依然保存在二进制 binary 所占用的内存中 + } + + println!("static_string reference remains alive: {}", static_string); +} +``` + +4、 `&'static` 可以被强转成一个较短的生命周期 + +**Example** +```rust,editable +// 声明一个 static 常量,它拥有 `'static` 生命周期. +static NUM: i32 = 18; + +// 返回常量 `Num` 的引用,注意,这里的生命周期从 `'static` 强转为 `'a` +fn coerce_static<'a>(_: &'a i32) -> &'a i32 { + &NUM +} + +fn main() { + { + let lifetime_num = 9; + + let coerced_static = coerce_static(&lifetime_num); + + println!("coerced_static: {}", coerced_static); + } + + println!("NUM: {} stays accessible!", NUM); +} +``` + + + +## T: 'static + +关于 `'static` 的特征约束详细解释,请参见 [Rust 语言圣经](https://course.rs/advance/lifetime/static.html#t-static),这里就不再赘述。 + +5、🌟🌟 +```rust,editable +/* 让代码工作 */ +use std::fmt::Debug; + +fn print_it( input: T) { + println!( "'static value passed in is: {:?}", input ); +} + +fn print_it1( input: impl Debug + 'static ) { + println!( "'static value passed in is: {:?}", input ); +} + + +fn print_it2( input: &T) { + println!( "'static value passed in is: {:?}", input ); +} + +fn main() { + // i 是有所有权的数据,并没有包含任何引用,因此它是 'static + let i = 5; + print_it(i); + + // 但是 &i 是一个引用,生命周期受限于作用域,因此它不是 'static + print_it(&i); + + print_it1(&i); + + // 但是下面的代码可以正常运行 ! + print_it2(&i); +} +``` + + +6、🌟🌟🌟 ```rust,editable use std::fmt::Display;