我用Rust写了一个简单的程序.这个程序可以编译.

use std::cell::{Ref, RefCell};

fn print_number(x: &i32) {
    println!("x is {}", x);
}

fn main() {
    let stack: i32 = 42;
    let reference: &i32 = &stack;
    let refcell: RefCell<&i32> = RefCell::new(reference);
    let wrapped: Ref<'_, &i32> = refcell.borrow();

    print_number(&wrapped);
    print_number(*wrapped);
}

我可以说出两者都有效的原因:

  1. &是有效的,因为&wrapped是类型&Ref<&i32>,可以被反胁迫为&&i32,后者可以被反胁迫为&i32.
  2. *行,因为*wrapped等于*Deref::deref(&wrapped).我们知道Deref::deref(&Ref<&i32>)个结果对应&&i32个结果,所以*Deref::deref(&Ref<&i32>)个结果对应*&&i32个结果,即&i32个.

第二种方法(*)似乎更直接,但是Rust编译器建议我使用第一种方法(&).如果我添加一行:

print_number(wrapped);

这当然不能编译.但我对编译报告很感兴趣:

error[E0308]: mismatched types
  --> src/main.rs:16:18
   |
16 |     print_number(wrapped);
   |     ------------ ^^^^^^^ expected `&i32`, found `Ref<'_, &i32>`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected reference `&i32`
                 found struct `Ref<'_, &i32>`
note: function defined here
  --> src/main.rs:3:4
   |
3  | fn print_number(x: &i32) {
   |    ^^^^^^^^^^^^ -------
help: consider borrowing here
   |
16 |     print_number(&wrapped);
   |                  +

For more information about this error, try `rustc --explain E0308`.
error: could not compile `testrust` (bin "testrust") due to 1 previous error

在报告的"帮助"中,它建议我加&.我想知道为什么它不建议我加*分.

推荐答案

建议&修复Ref<'_, T>中任何类型T的代码,而*仅在所包含的类型实现Copy并且是引用时才起作用.Copy是必需的,因为否则你不能"移出"Ref和一个引用,因为你的函数要求它的参数是1.特殊的大小写"T是一个共享引用"(它包括ISCopy,因为共享引用总是如此)似乎没有那么有用,如果另一个,并且在某些情况下已经需要实现,推荐&的方式也工作并产生相同的程序集.

换句话说,在这里推荐*&需要额外的代码(=更多的工作),而没有人机工程学或性能增益.

Rust相关问答推荐

如何在Rust中在屏幕中间打印内容?

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

MutexGuard中的过滤载体不需要克隆

S在Cargo.toml中添加工作空间开发依赖关系的正确方法是什么?

为什么rustc会自动降级其版本?

使用 pyo3 将 Rust 转换为 Python 自定义类型

信号量释放后 Rust 输出挂起线程

为什么是&mut发送?线程如何在安全的 Rust 中捕获 &mut?

sha256 摘要仅适用于 &*

无法将`&Vec>`转换为`&[&str]`

一旦令牌作为文字使用,声明宏不匹配硬编码值?

哪些特征通过 `Deref` 而哪些不通过?

无法理解 Rust 对临时值的不可变和可变引用是如何被删除的

返回引用字符串的future

具有生命周期和以后引用的可变方法

Cargo:如何将整个目录或文件包含在功能标志中?

为什么这个 Trait 无效?以及改用什么签名?

基于名称是否存在的条件编译

为什么这里需要类型注解?

为什么 Rust 中的关联类型需要明确的生命周期注释?