为什么这段代码能够编译?
fn get_iter() -> impl Iterator<Item = i32> {
[1, 2, 3].iter().map(|&i| i)
}
fn main() {
let _it = get_iter();
}
[1, 2, 3]
是一个局部变量,iter()
借用它。这段代码不应该编译,因为返回的值持有对局部变量的引用。
为什么这段代码能够编译?
fn get_iter() -> impl Iterator<Item = i32> {
[1, 2, 3].iter().map(|&i| i)
}
fn main() {
let _it = get_iter();
}
[1, 2, 3]
是一个局部变量,iter()
借用它。这段代码不应该编译,因为返回的值持有对局部变量的引用。
[1, 2, 3]
并不被视为局部变量,而是静态变量!fn foo() -> &'static [i32] {
&[1, 2, 3]
}
这很有效!
不久前,RFC 1414:Rvalue Static Promotion被合并:“将constexpr rvalues提升为静态内存中的值,而不是堆栈插槽中的值”。这意味着你编写的基本上所有文字都可以永久存在。因此,像let _: &'static i32 = &42;
这样的东西也可以工作!
如果我们避免使用文字数组,就可以看到预期的错误:
fn bar() -> impl Iterator<Item = i32> {
vec![1, 2, 3].iter().map(|&i| i)
}
v
does not live long enough”错误。fn promote_integer() -> &'static i32 {
&42
}
fn promote_float() -> &'static f64 {
&42.42
}
fn promote_str() -> &'static str {
"Hello World!"
}
struct Foo(char);
fn promote_struct() -> &'static Foo {
&Foo('x')
}
const
函数的结果是否可以自动提升为static
仍然是一个开放性话题。
&42
是否会强制编译器将42
存储在静态内存中,而不是将其作为内联处理? - Alexey