为什么变量范围取决于定义顺序?
Why is variable scope dependent on the definition order?
我有一个基本的(可能是愚蠢的)所有权问题。我正在尝试从包裹在 Some(String)
中的 String
值创建一个 &str
的向量。我正在使用一个中间变量来存储 extracted/unwrapped String
并且似乎我需要在 向量之前定义这个中间变量 以满足借用检查器的要求:
工作代码:
fn main() {
let a = Some("a".to_string());
let mut val = String::new();
let mut v = Vec::<&str>::new();
if a.is_some() {
val = a.unwrap();
v.push(&val[..]);
}
println!("{:?}", val);
}
无效代码:
fn main() {
let a = Some("a".to_string());
let mut v = Vec::<&str>::new();
let mut val = String::new();
if a.is_some() {
val = a.unwrap();
v.push(&val[..]);
}
println!("{:?}", val);
}
编译器错误:
<anon>:9:17: 9:20 error: `val` does not live long enough
<anon>:9 v.push(&val[..]);
^~~
<anon>:4:35: 12:2 note: reference must be valid for the block suffix following statement 1 at 4:34...
<anon>:4 let mut v = Vec::<&str>::new();
<anon>:5 let mut val = String::new();
<anon>:6
<anon>:7 if a.is_some() {
<anon>:8 val = a.unwrap();
<anon>:9 v.push(&val[..]);
...
<anon>:5:32: 12:2 note: ...but borrowed value is only valid for the block suffix following statement 2 at 5:31
<anon>:5 let mut val = String::new();
<anon>:6
<anon>:7 if a.is_some() {
<anon>:8 val = a.unwrap();
<anon>:9 v.push(&val[..]);
<anon>:10 }
...
error: aborting due to previous error
playpen: application terminated with error code 101
问题是:为什么我必须在向量v
之前定义val
变量?正如我所见,val
范围与 v
范围相同,还是我遗漏了什么?
绑定以声明的相反顺序被删除,即最近声明的东西首先被销毁。具体来说,在不起作用的代码中,val
的析构函数在 v
的析构函数之前运行。如果不仔细考虑 Vec<&str>::drop()
的作用,这是不安全的:例如,它可以尝试查看它包含的字符串切片的内容,尽管它们派生的 String
已经是销毁。
Vec
实际上并没有这样做,但其他合法类型会按照这些思路做一些事情。以前不可能安全地为包含 lifetimes/borrowed 指针的类型实现 Drop
。 relatively recent change 通过引入这些附加限制使其变得安全。
请注意,如果您声明 let v, val;
或 let val, v;
并稍后分配,这两个绑定 do 具有相同的生命周期,因此并非不可能相同生命周期的两个变量。
我有一个基本的(可能是愚蠢的)所有权问题。我正在尝试从包裹在 Some(String)
中的 String
值创建一个 &str
的向量。我正在使用一个中间变量来存储 extracted/unwrapped String
并且似乎我需要在 向量之前定义这个中间变量 以满足借用检查器的要求:
工作代码:
fn main() {
let a = Some("a".to_string());
let mut val = String::new();
let mut v = Vec::<&str>::new();
if a.is_some() {
val = a.unwrap();
v.push(&val[..]);
}
println!("{:?}", val);
}
无效代码:
fn main() {
let a = Some("a".to_string());
let mut v = Vec::<&str>::new();
let mut val = String::new();
if a.is_some() {
val = a.unwrap();
v.push(&val[..]);
}
println!("{:?}", val);
}
编译器错误:
<anon>:9:17: 9:20 error: `val` does not live long enough
<anon>:9 v.push(&val[..]);
^~~
<anon>:4:35: 12:2 note: reference must be valid for the block suffix following statement 1 at 4:34...
<anon>:4 let mut v = Vec::<&str>::new();
<anon>:5 let mut val = String::new();
<anon>:6
<anon>:7 if a.is_some() {
<anon>:8 val = a.unwrap();
<anon>:9 v.push(&val[..]);
...
<anon>:5:32: 12:2 note: ...but borrowed value is only valid for the block suffix following statement 2 at 5:31
<anon>:5 let mut val = String::new();
<anon>:6
<anon>:7 if a.is_some() {
<anon>:8 val = a.unwrap();
<anon>:9 v.push(&val[..]);
<anon>:10 }
...
error: aborting due to previous error
playpen: application terminated with error code 101
问题是:为什么我必须在向量v
之前定义val
变量?正如我所见,val
范围与 v
范围相同,还是我遗漏了什么?
绑定以声明的相反顺序被删除,即最近声明的东西首先被销毁。具体来说,在不起作用的代码中,val
的析构函数在 v
的析构函数之前运行。如果不仔细考虑 Vec<&str>::drop()
的作用,这是不安全的:例如,它可以尝试查看它包含的字符串切片的内容,尽管它们派生的 String
已经是销毁。
Vec
实际上并没有这样做,但其他合法类型会按照这些思路做一些事情。以前不可能安全地为包含 lifetimes/borrowed 指针的类型实现 Drop
。 relatively recent change 通过引入这些附加限制使其变得安全。
请注意,如果您声明 let v, val;
或 let val, v;
并稍后分配,这两个绑定 do 具有相同的生命周期,因此并非不可能相同生命周期的两个变量。