首页 > 解决方案 > 包含具有特征参数的结构的框的大小

问题描述

我需要一个包含特征对象及其本身的结构。令人失望的是,以下代码无法编译:

trait Foo {}

struct Bar<T: Foo> {
    bars: Vec<Box<Bar<dyn Foo>>>,
    foo: T,
}

?Sized我设法通过添加绑定来强制编译T,但我不明白为什么会这样。我认为这是因为所有 trait 对象都具有相同的大小,但 的大小Bar取决于具体类型的大小T。如果是这样,如何在内存中表示Bar一个未调整大小的?T特别是在堆上跟踪它的大小以及为什么不能在大小调整的情况下使用这种机制。

标签: compiler-errorsrusttraitstypechecking

解决方案


该类型dyn Foo在编译时没有已知的大小。因此,当您编写 时Bar<dyn Foo>,编译器将不允许这样做,因为(默认情况下)类型参数必须调整大小。编译器建议您通过允许未调整大小来解决此问题,这对于beT是必需的。Tdyn Foo

内存中没有大小Bar的表示如何?T

一个结构最多允许有一个未调整大小的字段。然后它的数据首先在内存中布局,首先是大小字段,然后是未大小字段。这个限制意味着所有字段的相对内存地址可以在编译时知道。具有?Sized类型参数的结构本身可以调整大小或不调整大小,具体取决于其参数的具体类型。当结构未调整大小时,它不能进入​​堆栈,因此您只能从指针后面使用它。

目前没有此类对象的文档。它不完全是一个特征对象,但它是一个指向可能没有调整大小的东西的指针。正如您的示例所示,这有效。但是我不能告诉你vtable指针存储在哪里,因为我不知道,我不知道如何找到。

特别是在堆上跟踪它的大小以及为什么不能在大小调整的情况下使用这种机制。

每个对象的大小实际上并没有改变——只是每个实例可能不同。该机制可以“在Sized案例中”使用,但您没有大小合适的案例!即使T是大小合适的,bars集合也将包含未调整大小的盒子Bar<dyn Foo>。这就是为什么您需要T: ?Sized(而不是T: !Sized)来说明这种类型适用于T调整大小或不调整大小。


推荐阅读