首先,我不是在问 &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
您正在移动可变引用,因为它被模式捕获。
以上所有内容都不足以向我自己解释它为何有效,但我没有基本原理来证明它。
为什么会这样?
最佳答案
This is a bug .我下面的原始分析完全忽略了它返回一个可变 引用这一事实。有关提升的部分仅在不可变 值的上下文中才有意义。
由于 rules governing temporaries 的细微差别,这是允许的(强调我的):
When using an rvalue in most lvalue contexts, a temporary unnamed lvalue is created and used instead, if not promoted to
'static
.
引用继续:
Promotion of an rvalue expression to a
'static
slot occurs when the expression could be written in a constant, borrowed, and dereferencing that borrow where the expression was the originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the resulting value does not contain interior mutability or destructors (these properties are determined based on the value where possible, e.g.&None
always has the type&'static Option<_>
, as it contains nothing disallowed).
您的第三个案例可以重写为“证明” '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
只是没有被存在的任何支票捕获。您可能会查找或提交描述情况的问题。
关于rust - 特征对象的 &mut 和 ref mut 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47680423/