有没有办法防止Weak :: new()过度分配?

时间:2017-06-15 18:41:40

标签: rust

Why doesn't Weak::new() work when Rc::downgrade() does?

的后续行动

当尝试以一种不要求它为底层类型分配内存的方式实现Weak::new()时,即使它永远不会被使用,我也遇到了障碍。

RcBox<T>的定义相当简单:

struct RcBox<T: ?Sized> {
    strong: Cell<usize>,
    weak: Cell<usize>,
    value: T,
}

此处的目标是创建一个实际上不包含任何RcBox<T>的{​​{1}}。基本上是value

然而,有一个障碍。 RcBox<()>是一个精简指针,但*mut RcBox<()>可能是一个胖指针。我们有这个胖指针的数据部分,但有很多不同的胖指针,所以试图合成其余的是

从链接问题中可以看出,我可以使它适用于特征对象:

*mut RcBox<T>

然而,这不能与impl<T: ?Sized> Weak<T> { pub fn new() -> Weak<T> { unsafe { let boxed = Box::into_raw(box RcBox { strong: Cell::new(0), weak: Cell::new(1), value: (), }); let ptr = if size_of::<*mut ()>() == size_of::<*mut T>() { let ptr: *mut RcBox<T> = transmute_copy(&boxed); ptr } else { let ptr: *mut RcBox<T> = transmute_copy(&TraitObject { data: boxed as *mut (), vtable: null_mut(), }); ptr }; Weak { ptr: Shared::new(ptr) } } } } 合作(例如)。

我再次尝试隔离str的固定大小部分,同时让编译器推断指针的胖部分:

RcBox

这听起来非常聪明,直到编译器压缩你的热情:

  
struct RcBox<T: ?Sized> {
    counters: RcBoxCounters<T>,
    value: T,
}

struct RcBoxCounters<T: ?Sized> {
    strong: Cell<usize>,
    weak: Cell<usize>,
    _phantom: PhantomData<T>,
}

impl<T: ?Sized> Weak<T> {
    pub fn new() -> Weak<T> {
        unsafe {
            let boxed = Box::into_raw(box RcBox::Counters::new(0, 1));
            Weak { ptr: Shared::new(boxed as *mut RcBox<T>) }
        }
    }
}

那是:

  • 我认为要让编译器合成胖部分,我需要error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions --> <anon>:58:40 | 58 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<RcBox<U>> for RcBox<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions | = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced = note: currently, 2 fields need coercions: counters (RcBoxCounters<T> to RcBoxCounters<U>), value (T to U) 中的PhantomData
  • 但这样做需要2次强制转换,这是不允许的。

那么,有没有办法修复RcBoxCounters以便它停止分配无关的(不必要的)内存?

注意:我的意思是只为两个计数器分配空间,然后分配大块并修剪后没有帮助。

注意:有人说过,可以使用Weak::new()或特殊值来表示缺少价值。这需要在每种方法上进行分支,这可能是不可取的。我更喜欢学会摆弄肥胖的指针。

1 个答案:

答案 0 :(得分:2)

是的,有一种方法,它实际上已提交到标准库:

  

此更改使Weak :: new()完全不分配内存。而是使用空指针创建它。使用弱项完成的唯一工作就是尝试升级,克隆和删除,这意味着代码实际上很少需要检查指针是否为空的地方。

相关问题