Arc::clone 的结果怎么会有“静态生命周期”?
How could the result of Arc::clone have a 'static lifetime?
让我们从 Arc
的典型示例开始
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let msg = Arc::new(Mutex::new(String::new()));
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = Arc::clone(&msg);
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
这会按预期编译和运行。然后我意识到也许 Mutex
不必存在于堆上并开始想知道我是否可以摆脱 Arc
并只使用对分配在堆栈上的 Mutex
的共享引用.这是我的尝试
use std::sync::Mutex;
use std::thread;
fn main() {
let msg = Mutex::new(String::new());
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = &msg;
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
虽然这个不能编译
error[E0597]: `msg` does not live long enough
--> src/main.rs:8:25
|
8 | let local_msg = &msg;
| ^^^^ borrowed value does not live long enough
9 | handles.push(thread::spawn(move || {
| ______________________-
10 | | let mut locked = local_msg.lock().unwrap();
11 | | locked.push_str("hello, world\n");
12 | | }));
| |__________- argument requires that `msg` is borrowed for `'static`
...
20 | }
| - `msg` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `hello`
To learn more, run the command again with --verbose.
编译器抱怨 local_msg
没有 'static
生命周期。嗯,它没有,所以这个错误是有道理的。但是,这意味着第一个片段中的变量 let local_msg = Arc::clone(&msg);
具有 'static
生命周期,否则我应该会得到类似的错误。
问题:
Arc::clone(&msg)
如何获得'static
生命?它指向的值在编译时是未知的,并且可能会在整个程序退出之前消失。
- 作为奖励,其他堆支持的智能指针如
Box
和 Rc
怎么样?它们是否都具有 'static
生命周期,因为借用检查器确保只要这些指针可见,它们指向的地址就始终有效?
编译器正在寻找的东西是生命周期绑定。生命周期绑定'a
并不意味着“此类型是生命周期[=的引用10=]”,而是“该类型包含的所有引用的生命周期至少为 'a
”。
(显式写入生命周期时,它看起来像 where T: 'a
。)
因此,任何 不包含 任何引用(或者更确切地说,没有生命周期参数)的类型都会自动满足 'static
生命周期界限。如果 T: 'static
,则 Arc<T>: 'static
(Box
和 Rc
也是如此)。
How could Arc::clone(&msg)
get a 'static lifetime? The value it points to isn't known at compile-time, and could die before the whole program exits.
它没有使用引用指向值,所以没问题。你的值的类型是Arc<Mutex<String>>
;这里没有生命周期参数,因为没有引用。如果假设是 Arc<'a, Mutex<String>>
(Arc
实际上没有的生命周期参数),那么该类型将不满足界限。
Arc
(或Rc
或Box
)的工作是拥有它指向的值。所有权不是参考,因此不受生命周期限制。
但是,如果您有 Arc<Mutex<&'a str>>
类型,那么它不会满足边界,因为它 包含一个引用 而不是 'static
。
让我们从 Arc
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let msg = Arc::new(Mutex::new(String::new()));
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = Arc::clone(&msg);
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
这会按预期编译和运行。然后我意识到也许 Mutex
不必存在于堆上并开始想知道我是否可以摆脱 Arc
并只使用对分配在堆栈上的 Mutex
的共享引用.这是我的尝试
use std::sync::Mutex;
use std::thread;
fn main() {
let msg = Mutex::new(String::new());
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = &msg;
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
虽然这个不能编译
error[E0597]: `msg` does not live long enough
--> src/main.rs:8:25
|
8 | let local_msg = &msg;
| ^^^^ borrowed value does not live long enough
9 | handles.push(thread::spawn(move || {
| ______________________-
10 | | let mut locked = local_msg.lock().unwrap();
11 | | locked.push_str("hello, world\n");
12 | | }));
| |__________- argument requires that `msg` is borrowed for `'static`
...
20 | }
| - `msg` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `hello`
To learn more, run the command again with --verbose.
编译器抱怨 local_msg
没有 'static
生命周期。嗯,它没有,所以这个错误是有道理的。但是,这意味着第一个片段中的变量 let local_msg = Arc::clone(&msg);
具有 'static
生命周期,否则我应该会得到类似的错误。
问题:
Arc::clone(&msg)
如何获得'static
生命?它指向的值在编译时是未知的,并且可能会在整个程序退出之前消失。- 作为奖励,其他堆支持的智能指针如
Box
和Rc
怎么样?它们是否都具有'static
生命周期,因为借用检查器确保只要这些指针可见,它们指向的地址就始终有效?
编译器正在寻找的东西是生命周期绑定。生命周期绑定'a
并不意味着“此类型是生命周期[=的引用10=]”,而是“该类型包含的所有引用的生命周期至少为 'a
”。
(显式写入生命周期时,它看起来像 where T: 'a
。)
因此,任何 不包含 任何引用(或者更确切地说,没有生命周期参数)的类型都会自动满足 'static
生命周期界限。如果 T: 'static
,则 Arc<T>: 'static
(Box
和 Rc
也是如此)。
How could
Arc::clone(&msg)
get a 'static lifetime? The value it points to isn't known at compile-time, and could die before the whole program exits.
它没有使用引用指向值,所以没问题。你的值的类型是Arc<Mutex<String>>
;这里没有生命周期参数,因为没有引用。如果假设是 Arc<'a, Mutex<String>>
(Arc
实际上没有的生命周期参数),那么该类型将不满足界限。
Arc
(或Rc
或Box
)的工作是拥有它指向的值。所有权不是参考,因此不受生命周期限制。
但是,如果您有 Arc<Mutex<&'a str>>
类型,那么它不会满足边界,因为它 包含一个引用 而不是 'static
。