Tim*_*ost 2 static lifetime rust
为什么我可以在同一范围内对静态类型进行多次可变引用?
我的代码:
static mut CURSOR: Option<B> = None;
struct B {
pub field: u16,
}
impl B {
pub fn new(value: u16) -> B {
B { field: value }
}
}
struct A;
impl A {
pub fn get_b(&mut self) -> &'static mut B {
unsafe {
match CURSOR {
Some(ref mut cursor) => cursor,
None => {
CURSOR= Some(B::new(10));
self.get_b()
}
}
}
}
}
fn main() {
// first creation of A, get a mutable reference to b and change its field.
let mut a = A {};
let mut b = a.get_b();
b.field = 15;
println!("{}", b.field);
// second creation of A, a the mutable reference to b and change its field.
let mut a_1 = A {};
let mut b_1 = a_1.get_b();
b_1.field = 16;
println!("{}", b_1.field);
// Third creation of A, get a mutable reference to b and change its field.
let mut a_2 = A {};
let b_2 = a_2.get_b();
b_2.field = 17;
println!("{}", b_1.field);
// now I can change them all
b.field = 1;
b_1.field = 2;
b_2.field = 3;
}
Run Code Online (Sandbox Code Playgroud)
我知道借款规则
&T资源的引用(),&mut T).在上面的代码中,我有一个结构A,其中get_b()包含返回可变引用的方法B.有了这个参考,我可以改变struct的字段B.
奇怪的是,可以在同一个scope(b, b_1, b_2)中创建多个可变引用,我可以使用它们来修改B.
为什么我有多个可变引用,其'static生命周期显示在main()?
我试图解释这个行为是因为我返回了一个带有'static生命的可变引用.每次我调用get_b()它都会返回相同的可变引用.最后,它只是一个相同的参考.这是正确的吗?为什么我能够使用从get_b()单独获得的所有可变引用?
这只有一个原因:你已经骗了编译器.您滥用unsafe代码并违反了Rust关于可变别名的核心原则.你声明你已经知道了借用规则,但是你会不遗余力地打破它们!
unsafe代码为您提供了一小部分额外功能,但作为交换,您现在负责避免所有可能的未定义行为.多个可变别名是未定义的行为.
static涉及的事实与问题完全正交.您可以使用您关心的任何生命周期创建对任何事物(或任何事物)的多个可变引用:
fn foo() -> (&'static i32, &'static i32, &'static i32) {
let somewhere = 0x42 as *mut i32;
unsafe { (&*somewhere, &*somewhere, &*somewhere) }
}
Run Code Online (Sandbox Code Playgroud)
在您的原始代码中,您声明get_b任何人都可以安全地进行呼叫.这不是真的.整个功能应该标记为不安全,以及关于什么是和不允许防止触发不安全的大量文档.任何unsafe然后块应该有相应的注解来解释为什么是特定的使用不破坏所需要的规则.所有这些使得创建和使用unsafe代码比安全代码更繁琐,但与C相比,其中每行代码都是概念性的unsafe,它仍然要好得多.
只有unsafe在比编译器更清楚的情况下才应该使用代码.对于大多数情况下的大多数人来说,创建unsafe代码的理由很少.
来自Firefox开发人员的具体提醒: