Add [&'static and T: 'static] chapter

This commit is contained in:
sunface 2022-03-29 21:55:18 +08:00
parent f501cbc737
commit addb6c6a80
5 changed files with 248 additions and 2 deletions

View File

@ -3,7 +3,9 @@
### 2022-03-29
- Add language switch icon in top-right corner
- Add [&'static and T: 'static](https://practice.rs/lifetime/static.html)
### 2022-03-28
- Add [Basic lifetime](https://practice.rs/lifetime/basic.html)

View File

@ -51,7 +51,7 @@
- [formating](formatted-output/formatting.md)
- [Lifetime](lifetime/intro.md)
- [basic](lifetime/basic.md)
- [&'static and T: 'static TODO](lifetime/static.md)
- [&'static and T: 'static](lifetime/static.md)
- [advance TODO](lifetime/advance.md)
- [Functional programing TODO](functional-programing/intro.md)
- [Closure](functional-programing/cloure.md)

View File

@ -1,5 +1,151 @@
# &'static and T: 'static
`'static` is a reserverd lifetime name, you might have encountered it serveral times:
```rust
// A reference with 'static lifetime:
let s: &'static str = "hello world";
// '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.
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。
```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");
}
```
2、 🌟🌟🌟🌟 Another way to make `'static` lifetime is using `Box::leak`
```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)
}
}
```
3、 🌟 `&'static` only indicates that the data can live forever, not the reference. The latter one will be constrained by its scope.
```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);
}
```
4、 `&'static` can be coerced to a shorter lifetime.
**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.
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 no。
5、🌟🌟
```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);
}
```
6、🌟🌟🌟
```rust,editable
use std::fmt::Display;

View File

@ -0,0 +1,98 @@
1、
```rust
fn main() {
let v: &str = "hello";
need_static(v);
println!("Success!")
}
fn need_static(r : &'static str) {
assert_eq!(r, "hello");
}
```
```rust
fn main() {
const v: &str = "hello";
need_static(v);
println!("Success!")
}
fn need_static(r : &'static str) {
assert_eq!(r, "hello");
}
```
2、
```rust
#[derive(Debug)]
struct Config {
a: String,
b: String,
}
static mut config: Option<&mut Config> = None;
fn init() -> Option<&'static mut Config> {
let c = Box::new(Config {
a: "A".to_string(),
b: "B".to_string(),
});
Some(Box::leak(c))
}
fn main() {
unsafe {
config = init();
println!("{:?}",config)
}
}
```
3、
```rust
fn main() {
// Make a `string` literal and print it:
let static_string = "I'm in read-only memory";
println!("static_string: {}", static_string);
println!("static_string reference remains alive: {}", static_string);
}
```
5、
```rust
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:
const i:i32 = 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);
}
```

BIN
zh-CN/.DS_Store vendored

Binary file not shown.