You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当T为非Copy类型时,解引用Box<T>为何不报“从共享引用移出”错误?

为什么*Box可以直接移动内部值,而自定义Deref类型不行?

先看第一个示例代码:

use std::ops::Deref;

struct Foo {}

fn main() {
    let b = Box::new(Foo{});
    
    let pb = *b; // 编译通过
    // let pb = *b.deref();  // 报错[E0507]: 无法从共享引用中移出值
}

这里的核心是:*Box的执行逻辑并非普通的*Box.deref()。Rust对Box<T>做了特殊语法支持,当你写*b时,编译器实际调用的是Box::into_inner(b)——这个方法会直接获取Box的所有权,把内部的T值完整转移出来,完全绕开了Deref trait的引用转换逻辑。

而b.deref()是显式调用Deref trait的方法,它返回的是&T类型的共享引用。对这个引用解引用*b.deref(),本质是尝试从共享引用里移出值,哪怕Foo是空结构体,它也不属于Copy类型,因此会触发报错。

再看自定义Deref类型的示例:

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; // 报错[E0507]: 无法从共享引用中移出值
    let pf = *f.deref(); // 报错[E0507]: 无法从共享引用中移出值
}

自定义类型的Deref实现没有特殊待遇,编译器会把*f自动展开成*(f.deref())——先通过deref()拿到内部值的共享引用,再尝试解引用移出值。对于非Copy的Vec<u8>来说,从共享引用里移动值违反了Rust的借用规则,因此两种写法都会报错。

总结:Box<T>是Rust的特殊类型,*Box是直接转移所有权取出内部值;而普通类型的Deref实现仅做引用转换,解引用操作不会触发所有权转移,只能通过引用访问内部值。

内容的提问来源于stack exchange,提问作者soupybionics

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:47:06