特征对象的&mut与ref mut之间的区别
首先,我不问自己&mut
和ref mut
之间有什么区别。
我问,因为我想:
let ref mut a = MyStruct
是相同的
let a = &mut MyStruct
考虑从函数返回一个特征对象。 你可以返回一个Box<Trait>
或一个&Trait
。 如果你想有可变的访问方法,是否有可能返回&mut Trait
?
给出这个例子:
trait Hello {
fn hello(&mut self);
}
struct English;
struct Spanish;
impl Hello for English {
fn hello(&mut self) {
println!("Hello!");
}
}
impl Hello for Spanish {
fn hello(&mut self) {
println!("Hola!");
}
}
该方法收到一个可变参考用于演示目的。
这不会编译:
fn make_hello<'a>() -> &'a mut Hello {
&mut English
}
也没有这个:
fn make_hello<'a>() -> &'a mut Hello {
let b = &mut English;
b
}
但是这将会编译和工作:
fn make_hello<'a>() -> &'a mut Hello {
let ref mut b = English;
b
}
我的理论
这个例子将使用不可变参考(不需要将其分配给变量,只返回&English
),但不包含可变引用。 我认为这是由于规则可以只有一个可变引用或者像你想要的那样多不可变。
在不可变引用的情况下,您正在创建一个对象并将其作为返回表达式借用; 它的参考不会因为借用而死。
在可变引用的情况下,如果您尝试创建一个对象并将其可变地作为返回表达式进行借用,那么您有两个可变引用(创建的对象及其可变引用)。 既然你不能对同一个对象有两个可变引用,它将不会执行第二个,因此这个变量将不能运行得足够长。 我认为,当你编写let mut ref b = English
并返回b
你正在移动可变引用,因为它是由模式捕获的。
以上所有内容都是向我自己解释为什么它有效的糟糕尝试,但我没有证据证明它的基本原理。
为什么会发生?
我也将这个问题交给了Reddit。
这是一个错误。 我原来的分析完全忽略了它返回一个可变引用的事实。 关于促销的细节只有在不变价值的背景下才有意义。
由于管理临时规则的细微差别,这是可以允许的(重点是我的):
在大多数左值上下文中使用右值时, 如果不提升为'static
, 则会创建并使用临时未命名左值。
该参考继续:
当表达式可以写入一个常量,借用和解引用时,将一个右值表达式提升为一个'static
槽'static
,即在不改变运行时行为的情况下借用表达式最初写入的地方。 也就是说,可以在编译时评估提升的表达式,并且结果值不包含内部可变性或析构函数(这些属性根据可能的值确定,例如&None
始终具有类型&'static Option<_>
,因为它不包含任何内容)。
您的第三个案例可以被重写为“证明” 'static
促销正在发生:
fn make_hello_3<'a>() -> &'a mut Hello {
let ref mut b = English;
let c: &'static mut Hello = b;
c
}
至于为什么ref mut
允许这样做,而&mut
不允许,我最好的猜测是'static
促销是尽力而为的,而&mut
只是不受任何检查的影响。 你可能会寻找或提出描述情况的问题。
上一篇: Difference between &mut and ref mut for trait objects
下一篇: Understanding the scalability of RShiny apps hosted on ShinyServer