首先,我不是在问&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上。
发布于 2017-12-06 18:46:22
这是个小虫子。我下面的原始分析完全忽略了这一事实,即它正在返回一个可变的引用。关于晋升的部分只有在不可改变的价值观的背景下才有意义。
由于临时人员管理规则 (重点雷)的细微差别,这是允许的:
在大多数lvalue上下文中使用rvalue时,将创建并使用一个临时的未命名的lvalue,如果不提升为
'static.,则使用。
这一提法继续说:
将rvalue表达式提升到
'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只是没有被任何检查所捕获。您可能会查找或提交一个描述情况的问题。
https://stackoverflow.com/questions/47680423
复制相似问题