#rust
#Ржавчина
Вопрос:
Когда я пытаюсь запустить это:
use std::thread::LocalKey;
struct Person {
name: String,
}
impl Person {
fn new(name: String) -> Self {
Person {
name: name,
}
}
fn name(amp;self) -> amp;str {
self.name.as_str()
}
}
thread_local! {
static NAMED_THING: Person = Person::new("John".to_string());
}
fn retrieve_name(p: amp;'static LocalKey<Person>) -> amp;str {
p.with(|n| n.name())
}
fn main() {
println!("The name is {}", retrieve_name(amp;NAMED_THING));
}
это говорит мне
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:24:18
|
24 | p.with(|n| n.name())
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 24:12...
--> src/main.rs:24:12
|
24 | p.with(|n| n.name())
| ^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:24:16
|
24 | p.with(|n| n.name())
| ^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that reference does not outlive borrowed content
Я мог бы сделать вместо этого:
fn retrieve_name(p: amp;'static LocalKey<Person>) -> amp;str {
p.with(|n| n.name().to_owned().as_str())
}
Но каждый раз клонировать эту строку кажется довольно расточительным. Не говоря уже о том, что теперь он говорит мне:
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:24:16
|
24 | p.with(|n| n.name().to_owned().as_str())
| -------------------^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
Ответ №1:
Вы не можете этого сделать.
Он Person
будет уничтожен, когда поток завершится, и тогда любая ссылка на него (например, 'static
ссылка, которая была отправлена в другой поток за это время) станет зависшей. Вот почему LocalKey
имеет with
метод вместо реализации Deref
, как lazy_static
это делают переменные: потому что использование 'static
ссылки на локальное значение потока является необоснованным.
Вам нужно организовать свой код так, чтобы все заимствования ограничивались областью действия переданного замыкания with
. Например:
fn print_name(p: amp;'static LocalKey<Person>) {
p.with(|n| println!("The name is {}", n.name()));
}
fn main() {
print_name(amp;NAMED_THING);
}