为什么`dyn Trait`不满足Sized约束?固定大小特性对象为何需要引用?
核心概念澄清
你产生疑问的核心原因是混淆了两个极易搞混的概念:dyn Trait 和指向它的指针类型。
dyn Trait本身是动态大小类型(DST),没有编译期可知的固定长度:不同实现了Trait的具体类型大小可能完全不同,所以dyn Trait无法直接存储在栈上,也不能直接作为函数参数传递,必须放在某种指针的后面。- 你教程里提到的「64位系统下占16字节、包含数据指针和vtable指针的结构」,本质就是指向
dyn Trait的指针,比如&dyn Trait、Box<dyn Trait>都属于这类,它们才是你说的胖指针,本身是固定大小的Sized类型。
设计一致性说明
Rust的指针设计逻辑完全统一,不存在你以为的不一致问题:
- 所有指向**编译期大小确定(Sized)**类型的指针,都是单
usize大小的瘦指针,比如&i32、&String、&&dyn Trait都是,最后那个例子里因为&dyn Trait本身是固定16字节的Sized类型,所以指向它的引用自然就是普通的瘦指针。 - 所有指向**动态大小(DST)**类型的指针,都是多
usize大小的胖指针,额外存储运行时需要的元信息:- 切片引用
&[T]是胖指针,额外存储数组长度 - trait对象引用
&dyn Trait是胖指针,额外存储vtable指针
两者的设计逻辑完全对齐,没有任何特殊处理。
- 切片引用
示例验证
我们可以通过标准库的size_of函数直观验证这个规则:
use std::mem::size_of; trait TestTrait {} impl TestTrait for i32 {} fn main() { // 64位系统下输出16,&dyn TestTrait是胖指针 println!("size_of::<&dyn TestTrait>() = {}", size_of::<&dyn TestTrait>()); // 64位系统下输出8,指向胖指针的引用是普通瘦指针 println!("size_of::<&&dyn TestTrait>() = {}", size_of::<&&dyn TestTrait>()); // 64位系统下输出16,切片引用也是胖指针,和trait对象引用逻辑一致 println!("size_of::<&[i32]>() = {}", size_of::<&[i32]>()); }
如果尝试直接打印size_of::<dyn TestTrait>(),编译器会直接报错,提示dyn TestTrait没有固定大小,无法计算长度,也验证了我们上面的结论。
内容的提问来源于stack exchange,提问作者zombiesauce
相关产品推荐
相关产品推荐

