我需要一个包含特征对象和更多自身特征的结构。令人失望的是以下代码无法编译:
trait Foo {}
struct Bar<T: Foo> {
bars: Vec<Box<Bar<dyn Foo>>>,
foo: T,
}
我设法通过添加绑定到?Sized
的{{1}}来强制编译,但是我不明白为什么会这样。我认为这是因为所有特征对象都具有相同的大小,但是T
的大小取决于具体类型Bar
的大小。如果是这样,如何在内存中表示T
且大小为Bar
的大小?具体来说,是什么跟踪其在堆上的大小,以及为何不能在大小写情况下使用此机制。
答案 0 :(得分:0)
类型dyn Foo
的大小在编译时未知。因此,当您编写Bar<dyn Foo>
时,编译器将不允许使用它,因为(默认情况下)必须调整类型参数的大小。编译器建议您通过允许对T
进行大小调整来解决此问题,这对于使T
为dyn Foo
是必要的。
在内存中表示
Bar
且大小为T
的大小如何?
一个结构最多可以有一个大小不一的字段。然后将其数据首先与大小字段一起放置在内存中,然后再将未大小字段放置在内存中。此限制意味着可以在编译时知道所有字段的相对内存地址。带有?Sized
类型参数的结构本身可以调整大小,也可以不调整大小,具体取决于其参数的具体类型。当该结构未调整大小时,它无法进入堆栈,因此只能从指针后面使用它。
目前没有有关此类对象的文档。它不完全是一个特征对象,但它是指向可能未调整大小的对象的指针。如您的示例所示,这可行。但是我无法告诉您vtable
指针的存储位置,因为我不知道,而且不确定如何查找。
具体是什么会跟踪其在堆上的大小,以及为什么不能在这种大小的情况下使用此机制。
每个对象的大小实际上并没有改变-每个实例可能有所不同。可以在Sized
情况下使用机制 ,但是没有大小限制!即使对于已调整大小的T
,bars
集合也将包含未调整大小的Bar<dyn Foo>
框。因此,您需要T: ?Sized
(而不是T: !Sized
)来说这种类型适用于T
的大小或未大小。