&’static and T: ‘static
'static 是一个 Rust 保留的生命周期名称,在之前我们可能已经见过好几次了:
1. #![allow(unused)]
2. fn main() {
3. // 引用的生命周期是 'static :
4. let s: &'static str = "hello world";
6. // 'static 也可以用于特征约束中:
7. fn generic<T>(x: T) where T: 'static {}
8. }
虽然它们都是 'static,但是也稍有不同。
&’static
作为一个引用生命周期,&'static 说明该引用指向的数据可以跟程序活得一样久,但是该引用的生命周期依然有可能被强转为一个更短的生命周期。
- 🌟🌟 有好几种方法可以将一个变量标记为
'static生命周期, 其中两种都是和保存在二进制文件中相关( 例如字符串字面量就是保存在二进制文件中,它的生命周期是'static)。
2. /* 使用两种方法填空 */
3. fn main() {
4. __;
5. need_static(v);
7. println!("Success!")
8. }
10. fn need_static(r : &'static str) {
11. assert_eq!(r, "hello");
12. }
- 🌟🌟🌟🌟 使用
Box::leak也可以产生'static生命周期
1. #[derive(Debug)]
2. struct Config {
3. a: String,
4. b: String,
5. }
6. static mut config: Option<&mut Config> = None;
8. /* 让代码工作,但不要修改函数的签名 */
9. fn init() -> Option<&'static mut Config> {
10. Some(&mut Config {
11. a: "A".to_string(),
12. b: "B".to_string(),
13. })
14. }
16. fn main() {
17. unsafe {
18. config = init();
20. println!("{:?}",config)
21. }
22. }
- 🌟
&'static只能说明引用指向的数据是能一直存活的,但是引用本身依然受限于它的作用域
1. fn main() {
2. {
3. // 字符串字面量能跟程序活得一样久,因此 `static_string` 的生命周期是 `'static`
4. let static_string = "I'm in read-only memory";
5. println!("static_string: {}", static_string);
7. // 当 `static_string` 超出作用域时,该引用就无法再被使用,但是引用指向的数据( 字符串字面量 ) 依然保存在二进制 binary 所占用的内存中
8. }
10. println!("static_string reference remains alive: {}", static_string);
11. }
&'static可以被强转成一个较短的生命周期
Example
1. // 声明一个 static 常量,它拥有 `'static` 生命周期.
2. static NUM: i32 = 18;
4. // 返回常量 `Num` 的引用,注意,这里的生命周期从 `'static` 强转为 `'a`
5. fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
6. &NUM
7. }
9. fn main() {
10. {
11. let lifetime_num = 9;
13. let coerced_static = coerce_static(&lifetime_num);
15. println!("coerced_static: {}", coerced_static);
16. }
18. println!("NUM: {} stays accessible!", NUM);
19. }
T: ‘static
关于 'static 的特征约束详细解释,请参见 Rust 语言圣经,这里就不再赘述。
- 🌟🌟
1. /* 让代码工作 */
2. use std::fmt::Debug;
4. fn print_it<T: Debug + 'static>( input: T) {
5. println!( "'static value passed in is: {:?}", input );
6. }
8. fn print_it1( input: impl Debug + 'static ) {
9. println!( "'static value passed in is: {:?}", input );
10. }
12. fn print_it2<T: Debug + 'static>( input: &T) {
13. println!( "'static value passed in is: {:?}", input );
14. }
16. fn main() {
17. // i 是有所有权的数据,并没有包含任何引用,因此它是 'static
18. let i = 5;
19. print_it(i);
21. // 但是 &i 是一个引用,生命周期受限于作用域,因此它不是 'static
22. print_it(&i);
24. print_it1(&i);
26. // 但是下面的代码可以正常运行 !
27. print_it2(&i);
28. }
- 🌟🌟🌟
1. use std::fmt::Display;
3. fn main() {
4. let mut string = "First".to_owned();
6. string.push_str(string.to_uppercase().as_str());
7. print_a(&string);
8. print_b(&string);
9. print_c(&string); // Compilation error
10. print_d(&string); // Compilation error
11. print_e(&string);
12. print_f(&string);
13. print_g(&string); // Compilation error
14. }
16. fn print_a<T: Display + 'static>(t: &T) {
17. println!("{}", t);
18. }
20. fn print_b<T>(t: &T)
21. where
22. T: Display + 'static,
23. {
24. println!("{}", t);
25. }
27. fn print_c(t: &'static dyn Display) {
28. println!("{}", t)
29. }
31. fn print_d(t: &'static impl Display) {
32. println!("{}", t)
33. }
35. fn print_e(t: &(dyn Display + 'static)) {
36. println!("{}", t)
37. }
39. fn print_f(t: &(impl Display + 'static)) {
40. println!("{}", t)
41. }
43. fn print_g(t: &'static String) {
44. println!("{}", t);
45. }
你可以在这里找到答案(在 solutions 路径下)
