Sized是 Rust 中一个极其特殊的标记 TraitMarker Trait它既没有方法也极少需要手动实现但却深刻地影响着 Rust 的类型系统、内存布局和 trait 对象的使用方式。1、什么是SizedSized的定义极其简单位于std::marker模块中pubtraitSized{}一个类型在编译期具有固定且已知的大小。Rust 中绝大多数类型都是Sized的包括所有基本类型、结构体、枚举、数组、元组等。如果一个类型的大小在编译期无法确定它就被称为动态大小类型DST, Dynamically Sized Type。典型的 DST 包括切片类型[T]字符串切片str不是strtrait 对象dyn Trait包含一个 DST 作为最后一个字段的结构体// 这些都是 DST无法直接使用lets:str*hello;// 编译错误size 未知letarr:[i32][1,2,3];// 编译错误size 未知letdyn_obj:dynDisplay...;// 编译错误size 未知由于 DST 的大小未知它们无法被放在栈上也不能作为函数参数按值传递。只能在指针后面使用它们比如str、[T]、Boxdyn Trait等。2、隐式 Sized 绑定Rust 的类型参数默认是Sized的。这意味着当你写一个泛型函数时编译器实际上帮你在内部添加了Sized约束// 你写的代码fnfooT(x:T){...}// 编译器实际看到的fnfooT:Sized(x:T){...}这种隐式绑定覆盖了以下场景泛型类型参数T泛型结构体/枚举中的字段impl Trait的返回类型3、 使用?Sized解除限制当你需要在泛型中接受 DST 时需要使用特殊语法?Sized意为T可以是 Sized 的也可以不是。// 解除 Sized 限制T 可以是 DSTfnbarT:?Sized(x:T){// x 是指针所以即使 T 是 DST 也没问题}?Sized只能在以下位置使用泛型类型参数T: ?Sized结构体泛型参数的最后一个字段struct ST: ?Sized { tail: T }不能在关联类型、trait 自身定义或函数返回值中使用。usestd::fmt::Debug;fnprint_testT:Debug?Sized(t:T){println!({:?},t);}fnmain(){print_test(ssss);print_test([2,5,6]);print_test(35);}4、标准库中的应用类型/模块应用方式说明BoxTimplT: ?Sized BoxTBox可以指向堆上的 DST如Box[i32]或Boxdyn Error。RcT/ArcTimplT: ?Sized RcT引用计数指针也可以指向 DST。std::fmt::Debugtrait Debug: ?Sized允许对str、[i32]等切片直接调用.fmt()。AsRefTimplT: ?Sized, U: ?Sized AsRefU for T许多转换逻辑需要处理不定长类型。5、Sized和?Sized的使用默认不动在绝大多数泛型编程中保持默认的Sized约束。这保证了类型可以按值传递、存储在栈上且性能最优。需要灵活性时用?Sized当你的函数接收的是引用T或智能指针BoxT且你希望它能通吃“具体类型”和“切片/Trait对象”时。典型签名fn fooT: ?Sized(x: T)。设计 Trait 时注意如果希望 Trait 能被用作dyn Trait不要给 Trait 本身加Sized约束。如果 Trait 中的某些方法依赖于静态大小如返回Self给该方法加where Self: Sized。理解Sized和?Sized的核心在于明白**Rust 默认追求静态确定的内存布局而?Sized是为了在必要时通过指针间接访问打破这一限制以支持多态和切片操作。