有时可以移动特征

Trait can be sometimes moved

我有一个特征看起来像

trait Trait<T>
    where T: Data
{
    fn m1(&self) -> bool;
    fn m2(self) -> Box<dyn Trait<T>>;
}

为什么 m2 方法 self 甚至被允许?它不像任何 trait impls 可以调用该方法,因为:

cannot move a value of type dyn Trait<T>: the size of dyn Trait<T> cannot be statically determined

这个错误是有道理的,但为什么我可以 pushVec 这样的容器中的特征对象:

let trait_object: Box<dyn Trait<T>> = e;
let mut new_vec = Vec::new();
new_vec.push(trait_object)

那么,如果无法移动特征对象,为什么 new_vec.push(trait_object) 有效?

dyn Trait<T>是一个特征对象,它不同于具有实现特征的约束类型变量。

特征对象使用动态调度并且在 compile-time 处不知道大小 - 这就是为什么您几乎总是看到 & 引用或装箱后的特征对象。这就是错误消息显示 the size of dyn Trait<T> cannot be statically determined.

的原因

您的特征可以针对任何具体 (Sized) 类型实现。例如,对于 i32:

impl Trait<String> for i32
where
    T: Data,
{
    fn m1(&self) -> bool {
        true
    }

    // Can take self here because i32 is Sized
    fn m2(self) -> Box<dyn Trait2<T>> {
         make_boxed_trait_t(String::new())
    }
}

why can I can push trait objects in a container like Vec like so:

之所以可行,是因为您的示例中的特征对象被装箱了。 dyn Trait<T> 未调整大小,但 Box<dyn Trait<T>> 的大小在编译时已知。 size是两个指针的大小,因为一个装箱的trait对象的布局总是一个指向数据的指针和一个指向Trait.

类型实现的vtable的指针