Add [&'static and T: 'static] chapter
This commit is contained in:
parent
f501cbc737
commit
addb6c6a80
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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