rust-by-practice/en/src/lifetime/static.md

198 lines
4.4 KiB
Markdown
Raw Normal View History

2022-02-11 00:42:25 -06:00
# &'static and T: 'static
2022-10-29 04:44:44 -05:00
`'static` is a reserved lifetime name, you might have encountered it several times:
2022-03-29 07:55:18 -06:00
```rust
// A reference with 'static lifetime:
let s: &'static str = "hello world";
2022-02-11 00:42:25 -06:00
2022-03-29 07:55:18 -06:00
// 'static as part of a trait bound:
fn generic<T>(x: T) where T: 'static {}
```
Though they are all `'static`, but subtly different.
## &'static
As a reference lifetime, `&'static` indicates the data pointed to by the reference lives as long as the running program. But it can still be coerced to a shorter lifetime.
2022-10-29 04:44:44 -05:00
1、🌟🌟 There are several ways to make a variable with `'static` lifetime, two of them are stored in the read-only memory of the binary.
2022-03-29 07:55:18 -06:00
```rust,editable
/* Fill in the blank in two ways */
fn main() {
__;
need_static(v);
println!("Success!")
}
fn need_static(r : &'static str) {
assert_eq!(r, "hello");
}
```
2022-11-06 22:02:49 -06:00
2. 🌟🌟🌟🌟 Another way to make `'static` lifetime is using `Box::leak`
2022-03-29 07:55:18 -06:00
```rust,editable
#[derive(Debug)]
struct Config {
a: String,
b: String,
}
static mut config: Option<&mut Config> = None;
/* Make it work without changing the function signatures of `init`*/
fn init() -> Option<&'static mut Config> {
Some(&mut Config {
a: "A".to_string(),
b: "B".to_string(),
})
}
fn main() {
unsafe {
config = init();
println!("{:?}",config)
}
}
```
2022-11-06 22:02:49 -06:00
3. 🌟 `&'static` only indicates that the data can live forever, not the reference. The latter one will be constrained by its scope.
2022-03-29 07:55:18 -06:00
```rust,editable
fn main() {
{
// Make a `string` literal and print it:
let static_string = "I'm in read-only memory";
println!("static_string: {}", static_string);
// When `static_string` goes out of scope, the reference
// can no longer be used, but the data remains in the binary.
}
println!("static_string reference remains alive: {}", static_string);
}
```
2022-11-06 22:02:49 -06:00
4. `&'static` can be coerced to a shorter lifetime.
2022-03-29 07:55:18 -06:00
**Example**
```rust,editable
// Make a constant with `'static` lifetime.
static NUM: i32 = 18;
// Returns a reference to `NUM` where its `'static`
// lifetime is coerced to that of the input argument.
fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
&NUM
}
fn main() {
{
// Make an integer to use for `coerce_static`:
let lifetime_num = 9;
// Coerce `NUM` to lifetime of `lifetime_num`:
let coerced_static = coerce_static(&lifetime_num);
println!("coerced_static: {}", coerced_static);
}
println!("NUM: {} stays accessible!", NUM);
}
```
## T: 'static
As a trait bound, it means the type does not contain any non-static references. Eg. the receiver can hold on to the type for as long as they want and it will never become invalid until they drop it.
2022-11-06 18:27:51 -06:00
2022-10-13 02:11:30 -05:00
It's important to understand this means that any owned data always passes a `'static `lifetime bound, but a reference to that owned data generally does not.
2022-03-29 07:55:18 -06:00
2022-11-06 22:02:49 -06:00
5. 🌟🌟
2022-03-29 07:55:18 -06:00
```rust,editable
/* Make it work */
use std::fmt::Debug;
fn print_it<T: Debug + 'static>( 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<T: Debug + 'static>( input: &T) {
println!( "'static value passed in is: {:?}", input );
}
fn main() {
// i is owned and contains no references, thus it's 'static:
let i = 5;
print_it(i);
// oops, &i only has the lifetime defined by the scope of
// main(), so it's not 'static:
print_it(&i);
print_it1(&i);
// but this one WORKS !
print_it2(&i);
}
```
2022-11-06 22:02:49 -06:00
6. 🌟🌟🌟
2022-02-11 00:42:25 -06:00
```rust,editable
use std::fmt::Display;
fn main() {
let mut string = "First".to_owned();
string.push_str(string.to_uppercase().as_str());
print_a(&string);
print_b(&string);
print_c(&string); // Compilation error
print_d(&string); // Compilation error
print_e(&string);
print_f(&string);
print_g(&string); // Compilation error
}
fn print_a<T: Display + 'static>(t: &T) {
println!("{}", t);
}
fn print_b<T>(t: &T)
where
T: Display + 'static,
{
println!("{}", t);
}
fn print_c(t: &'static dyn Display) {
println!("{}", t)
}
fn print_d(t: &'static impl Display) {
println!("{}", t)
}
fn print_e(t: &(dyn Display + 'static)) {
println!("{}", t)
}
fn print_f(t: &(impl Display + 'static)) {
println!("{}", t)
}
fn print_g(t: &'static String) {
println!("{}", t);
}
2022-10-13 02:11:30 -05:00
```