>访问结构体的字段以进行读取生锈游戏围栏:
use std::sync::Mutex;
#[deriving(Show)]
struct Test{
a: uint,
}
impl Test{
fn new() -> Test{
Test { a: 0}
}
fn get(&self) -> uint {
self.a
}
}
fn main() {
let t = Test{a: 42};
let m = Mutex::new(Test::new());
println!("Getting t: {} where t.a = {}", t.get(), t.a);
{
let m2 = m.lock();
println!("m2.a = {}", m2.a); // works
//println!("m2.get() = {}", m2.get()); // error: cannot borrow immutable local variable `m2` as mutable
}
}
因此,在这种情况下,访问字段m2.a
有效,但调用m2.get()
需要m2
可变,尽管get不会改变任何东西,也不会声明为正在改变任何东西,尤其是不&self
。
为了使这段代码正常工作,我可以用 let mut m2 = m.lock();
声明 m2
并且一切正常,但是为什么我在这里需要那个 mut,有没有更好的方法来调用m2.get()
而不声明m2
可变的,因为它适用于我声明为不可变并且仍然允许我调用t.get()
t
。
是的,编译器倾向于调用deref_mut
而不是deref
,以防两者都可用。在您的情况下,deref
就足够了并且有效,但隐式取消引用机制会选择deref_mut
,然后抱怨m2
不可变。
为了补充 reem 所说的,lock 对象确实实现了 Deref
和 DerefMut
这两个对象,如果你不需要可变借用,你可以通过显式地不可变地重新借用它来获取不可变的借用:
println!("m2.get() = {}", (&*m2).get());
如果这种访问是你所需要的,你也可以写
let m2 = m.lock();
let m2 = &*m2;
然后允许
println!("m2.get() = {}", m2.get());
由于现在Deref
系列的特征略有限制 - 即现在为同一类型实现Deref
和DerefMut
由于方法的 autoderef 行为而略有中断,即总是调用deref_mut
,甚至为了获取&
引用。
因此,MutexGuard
需要可变才能调用需要&self
的方法。通常,Mutex
的不可变用途很少见,而分别支持读写锁定的 RWLock
更适合此用例,因为它允许并发读锁定。