包含带有特征参数的结构的盒子的大小

时间:2018-08-05 04:04:03

标签: compiler-errors rust traits typechecking

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

trait Foo {}

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

我设法通过添加绑定到?Sized的{​​{1}}来强制编译,但是我不明白为什么会这样。我认为这是因为所有特征对象都具有相同的大小,但是T的大小取决于具体类型Bar的大小。如果是这样,如何在内存中表示T且大小为Bar的大小?具体来说,是什么跟踪其在堆上的大小,以及为何不能在大小写情况下使用此机制。

1 个答案:

答案 0 :(得分:0)

类型dyn Foo的大小在编译时未知。因此,当您编写Bar<dyn Foo>时,编译器将不允许使用它,因为(默认情况下)必须调整类型参数的大小。编译器建议您通过允许对T进行大小调整来解决此问题,这对于使Tdyn Foo是必要的。

  

在内存中表示Bar且大小为T的大小如何?

一个结构最多可以有一个大小不一的字段。然后将其数据首先与大小字段一起放置在内存中,然后再将未大小字段放置在内存中。此限制意味着可以在编译时知道所有字段的相对内存地址。带有?Sized类型参数的结构本身可以调整大小,也可以不调整大小,具体取决于其参数的具体类型。当该结构未调整大小时,它无法进入堆栈,因此只能从指针后面使用它。

目前没有有关此类对象的文档。它不完全是一个特征对象,但它是指向可能未调整大小的对象的指针。如您的示例所示,这可行。但是我无法告诉您vtable指针的存储位置,因为我不知道,而且不确定如何查找。

  

具体是什么会跟踪其在堆上的大小,以及为什么不能在这种大小的情况下使用此机制。

每个对象的大小实际上并没有改变-每个实例可能有所不同。可以在Sized情况下使用机制 ,但是没有大小限制!即使对于已调整大小的Tbars集合也将包含未调整大小的Bar<dyn Foo>框。因此,您需要T: ?Sized(而不是T: !Sized)来说这种类型适用于T的大小或未大小。