rust - 特征对象的 &mut 和 ref mut 之间的区别

标签 rust traits mutable trait-objects

首先,我不是在问 &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您正在移动可变引用,因为它被模式捕获。

以上所有内容都不足以向我自己解释它为何有效,但我没有基本原理来证明它。

为什么会这样?

我也cross-posted this question to Reddit .

最佳答案

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/

相关文章:

rust - 为什么不允许将 `self` 作为原始指针传递?

rust - rust 类型类型转换选项

scala - 混入嵌套在对象中的特征时出现 AbstractMethodError - 仅在编译和导入时

rust - 为什么 impl trait 不能用于返回多个/条件类型?

rust - 是否可以在运行时编译Vulkano着色器?

rust - 如何使用具有生命周期的类型作为 io::Error::new 的 `error` 参数?

C++ : discards qualifier even if the member variables are mutable

loops - 这是 transient 的正确用法吗?

rust - 需要 Sized 的特征与无法拥有该特征的特征对象有什么关系?

hash - 可变 HashMap 键是一种危险的做法吗?