为何Rust编译时无法确定常量数组字面量的大小?
我刚接触Rust,写了这段代码:
const strings: [&'static str] = ["Element 1", "Element 2", "Element 3"];
编译器报错说:
the size for values of type
[&'static str]cannot be known at compilation time
the traitSizedis not implemented for[&'static str]
我很疑惑:明明这个数组里明确有3个元素,编译器为什么不能在编译时识别它的固定长度?我发现只要把类型改成[&'static str; 3]或者&[&'static str]就能正常运行,但我搞不清楚这里的底层逻辑,到底忽略了什么?
要搞懂这个问题,得先理清Rust里几个和数组相关的核心类型区别:
[T]:动态大小类型(DST)
这个类型代表任意长度的连续T元素序列,它的大小在编译时是不确定的——因为理论上它可以是任何长度。Rust要求所有直接存在栈上的变量(包括常量)必须是Sized的(编译时能确定大小),而[T]并不实现Sizedtrait,所以你不能直接用它来声明常量或变量,这就是报错的根源。[T; N]:固定大小数组
这是Rust里真正的“固定长度数组”类型,N必须是编译期已知的常量。这个类型是Sized的,编译器能精确计算出它的内存大小(size_of::<T>() * N)。你手动加上3之后,就明确告诉编译器这是一个长度为3的固定数组,符合Sized要求,所以能正常编译。&[T]:切片引用
这是一个“胖指针”,包含两个部分:数据的起始内存地址,以及切片的长度。它本身是Sized的(比如64位系统下占16字节),所以可以用来声明变量/常量。当你把类型改成&[&'static str]时,编译器会自动把右边的固定数组转换成切片引用,本质上是存储了指向数组的指针和长度3,这也满足Sized要求。
另外补充一点:如果你不手动指定类型,Rust的类型推断会自动把["Element 1", ...]推断为[&'static str; 3],完全不需要你手动写长度。但你强制指定了[&'static str]这个动态大小类型,就触发了编译器的Sized检查错误。
内容的提问来源于stack exchange,提问作者Valerie Thiesent

