Add [&'static and T: 'static] chapter
This commit is contained in:
parent
f501cbc737
commit
addb6c6a80
|
@ -3,7 +3,9 @@
|
||||||
### 2022-03-29
|
### 2022-03-29
|
||||||
|
|
||||||
- Add language switch icon in top-right corner
|
- Add language switch icon in top-right corner
|
||||||
|
- Add [&'static and T: 'static](https://practice.rs/lifetime/static.html)
|
||||||
|
|
||||||
|
|
||||||
### 2022-03-28
|
### 2022-03-28
|
||||||
|
|
||||||
- Add [Basic lifetime](https://practice.rs/lifetime/basic.html)
|
- Add [Basic lifetime](https://practice.rs/lifetime/basic.html)
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
- [formating](formatted-output/formatting.md)
|
- [formating](formatted-output/formatting.md)
|
||||||
- [Lifetime](lifetime/intro.md)
|
- [Lifetime](lifetime/intro.md)
|
||||||
- [basic](lifetime/basic.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)
|
- [advance TODO](lifetime/advance.md)
|
||||||
- [Functional programing TODO](functional-programing/intro.md)
|
- [Functional programing TODO](functional-programing/intro.md)
|
||||||
- [Closure](functional-programing/cloure.md)
|
- [Closure](functional-programing/cloure.md)
|
||||||
|
|
|
@ -1,5 +1,151 @@
|
||||||
# &'static and T: 'static
|
# &'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
|
```rust,editable
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
```
|
Binary file not shown.
Loading…
Reference in New Issue