< 返回版块

O.O 发表于 2023-08-12 08:09

Tags:Box,Deref

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
    type Target = T;

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

我的理解是*self得到Box<T>**self得到T,最后返回T的引用。那**self是怎么取出T呢?

评论区

写评论
wangbyby 2023-08-14 22:43

可以打印mir出来:https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=7c3c6a45c599ffe00fc6cf4ac324799d deref对应这一段MIR。

    let mut _0: ();
    let _1: std::boxed::Box<usize>;
    let _2: ();
    let mut _3: &usize;
    let _4: &std::boxed::Box<usize>;
    let mut _5: std::boxed::Box<usize>;
    let mut _6: *const usize;
bb1: {
        _4 = &_1;
        _5 = deref_copy (*_4);
        _6 = (((_5.0: std::ptr::Unique<usize>).0: std::ptr::NonNull<usize>).0: *const usize);
        _7 = _6 as *const () (PtrToPtr);
        _8 = _7 as usize (Transmute);
        _9 = AlignOf(usize);
        _10 = Sub(_9, const 1_usize);
        _11 = BitAnd(_8, _10);
        _12 = Eq(_11, const 0_usize);
        assert(_12, "misaligned pointer dereference: address must be a multiple of {} but is {}", _9, _8) -> [success: bb6, unwind unreachable];
    }
    bb6: {
        _3 = &(*_6);
        _2 = test(move _3) -> [return: bb2, unwind: bb4];
    }

deref中&**self 分为:

  1. *self =》 *_4 解引用&Box<usize>
  2. &* =》 &(*_6) 解引用*const usize
GUO 2023-08-14 14:04

哈哈,有个万能答案,所有不能用常理解释的现象都可以认为是编译器做了内置处理。

就这个例子这样推测是合理的。 deref() 本质就是来实现操作符 * 重载的,实现了这个trait,就可以方便的使用 *obj 来解引用,它本质上是等同于 obj.deref() 回到本题, *self得到Box,**self(如果没有编译器内部魔法)想想会发生什么事?会形成对deref()的递归调用。所以我们就似懂非懂的推测是编译做了内部处理。

作者 O.O 2023-08-12 12:04

好的,我知道了

--
👇
night-cruise: 应该是编译器内部对 Box 做特殊处理了

night-cruise 2023-08-12 10:20

应该是编译器内部对 Box 做特殊处理了

1 共 4 条评论, 1 页