正如标题所述,为什么要编译以下代码?

use std::ops::Deref;

struct Foo {}

fn main() {
    let b = Box::new(Foo{});
    
    let pb = *b; //works
    // let pb = *b.deref();  // error[E0507]: cannot move out of a shared reference
}

对于具有非复制目标的自定义类型,情况并非如此.

use std::ops::Deref;

struct Foo<T> {
    p: T,
}

impl<T> Deref for Foo<T> {
    type Target = T;

    fn deref(&self) -> &<Self as Deref>::Target {
        &self.p
    }
}

fn main() {
    let f = Foo { p: vec![1u8] };

    let pf = *f; // error[E0507]: cannot move out of a shared reference
    let pf = *f.deref(); // error[E0507]: cannot move out of a shared reference
}

*Box不是*Box.deref()吗?

推荐答案

*Box不是*Box.deref()吗?

不,不是的.这是编译器的魔力之一--Box类型有点特殊,编译器会特别对待它.

看着the Deref implementation for Box给我们一个非常强烈的暗示,有些事情是不同的:

fn deref(&self) -> &T {
    &**self
}

如果这是任何其他类型,这将导致无限递归,但deref运算符(*)在应用于Box值时由编译器在内部处理.

允许您对box执行的特殊操作之一是移出其包含的值,这会产生销毁box并释放其堆分配的副作用.

(此外,不稳定的Box::into_inner()关联函数获取boxed: Self并简单地返回*boxed,这进一步说明了这一点.)

Rust相关问答推荐

如何在rust中有条件地分配变量?

如何从Rust记录WASM堆内存使用情况?

是否有可能同时避免不兼容的不透明类型和代码重复?

Rust:跨多个线程使用hashmap Arc和rwlock

带参考文献的 rust 元组解构

如何将单个 struct 实例与插入器一起传递到Rust中的映射

为什么BufReader实际上没有缓冲短寻道?

为什么比较Option<;字符串>;具有常数Option<&;str>;需要显式类型转换吗?

如何执行数组文字的编译时串联?

UnsafeCell:它如何通知 rustc Select 退出基于别名的优化?

带引脚和不带引脚的比较功能

为什么 js_sys Promise::new 需要 FnMut?

枚举的利基优化如何在 Rust 中工作?

如何从 rust 中的同一父目录导入文件

如何使用泛型满足 tokio 异步任务中的生命周期界限

如何在 Rust Polars 中可靠地连接 LazyFrames

如何在 Rust 中返回通用 struct

在 FFI 的上下文中,未初始化是什么意思?

为什么-x试图解析为文字并在声明性宏中失败?

如何重写这个通用参数?