我引用官方文档:
引用表示某个自有价值的借用。
来自C、Java、Perl和PHP,我看到了一个";参考";作为值的地址(或指针(。可以声明一个类型为"0"的变量;T";或对"0"型变量的引用(或指针(;T";(在Perl中使用&
-或(。
然而,我不确定这种表述是否完全适用于Rust。有件事困扰着我。
我总是看到";字符串切片";作为引用进行操作,即以其借用的形式(&str
(。
我(到目前为止(从未见过";str
";。
我试图声明一个类型为"的变量;str
〃;。。。但是编译器不允许我这么做。
问题:我们可以定义一个类型为"的变量吗;str
">
如果这是不可能的,那么这意味着我们面临的是一种除了作为引用之外无法声明的数据类型。这看起来很奇怪。。。
否,不能定义类型为str
的变量。这是因为变量是堆栈分配的,为了实现这一点,编译器需要在编译时知道变量的大小(这是一条通用规则,不是Rust特有的(。但是str: !Sized
,这意味着在编译时不能知道str
类型的值的大小。因此,str
必须始终分配到其他位置:例如,在堆上或数据段中。
但这并不意味着你被迫";隐藏";在借用&
之后,Rust中还有其他指针。例如,可以跨越&mut str
、*const str
、*mut str
、Rc<str>
、Box<str>
,并且列表会不断地进行
使用不稳定特性unsized_locals
,可以将动态大小的值移动到堆栈变量中:
#![feature(unsized_locals)]
fn main() {
let x: Box<str> = "abc".into();
let y: str = *x;
println!("{}", &y);
}
这个功能是不完整的——它只能在Rust编译器的夜间版本中使用,并且可能会出现错误行为。它可能永远不会进入一个稳定的Rust版本。
即便如此,也有充分的理由不这样做:您正在分配由输入数据决定的堆栈内存量。如果数据恰好大于您的堆栈以及使用堆栈的所有其他数据,那么您将面临堆栈溢出的巨大风险。
如今,您几乎从不需要无大小的本地:您可以始终将值放入Box
中(至少,如果您不是在没有内存分配器的情况下编程(。因此,缺少这个功能并不能真正限制你可以编写什么程序。但是,原则上,它可能存在。