包含具有特征参数的结构的框的大小

Size of a box containing a struct with a trait parameter

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

trait Foo {}

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

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

类型 dyn Foo 的大小在编译时未知。所以当你写 Bar<dyn Foo> 时,编译器不会允许它,因为(默认情况下)必须调整类型参数的大小。编译器建议您通过允许 T 未调整大小来解决此问题,这是 T 变为 dyn Foo 所必需的。

how is Bar with an unsized T represented in memory?

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

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

Specifically what tracks its size on the heap and why can not this mechanism be used in the sized case.

每个对象的大小实际上并没有改变 - 它只是每个实例可能不同。机制可以使用"in the Sized case",但你没有一个大小的案例!即使 T 已调整大小,bars 集合也将包含未调整大小的 Bar<dyn Foo> 框。这就是为什么您需要 T: ?Sized(与 T: !Sized 相对),表示此类型适用于 T 大小或未大小。