【发布时间】:2016-11-15 23:07:29
【问题描述】:
当我可以进行可变变量绑定时,为什么我需要重新绑定/隐藏?考虑:
let x = a();
let x = b(x);
对比
let mut x = a();
x = b(x);
可变变量绑定允许对该变量进行可变借用。 但是,与可变绑定相比,阴影是否有一些优势?
【问题讨论】:
标签: rust
当我可以进行可变变量绑定时,为什么我需要重新绑定/隐藏?考虑:
let x = a();
let x = b(x);
对比
let mut x = a();
x = b(x);
可变变量绑定允许对该变量进行可变借用。 但是,与可变绑定相比,阴影是否有一些优势?
【问题讨论】:
标签: rust
因为两者的效果完全不同。
要真正了解发生了什么,我们需要从头开始:什么是绑定?绑定是什么意思?
让我们考虑一个简单的函数:fn hello() -> String;。
当像这样调用这个函数时:
fn main() {
hello();
}
会发生什么?
该函数返回一个String,它会被立即丢弃(执行Drop,因为它正在释放其内存)。
结果被丢弃是因为它没有绑定变量名,语言规则说如果不绑定则可以立即丢弃1。
但是,如果我们绑定这个结果,我们会延长这个值的生命周期,并且我们可以通过这个绑定访问它......一段时间。
fn main() {
let value = hello();
std::mem::drop(value);
println!("{}", value); // Error: moved out of value
}
这是当前的问题:在 Rust 中,值的生命周期独立于绑定的范围。
一个值甚至不需要在其绑定退出其范围之前被删除:它可以转移到另一个值(类似于从函数返回)。
fn main() {
let x;
{
let y = hello();
x = y;
}
println!("{}", x);
}
1如果绑定到_,也会发生同样的情况。
所以,现在我们已经掌握了绑定和值不同的事实,让我们来看看这两个 sn-ps。
第一个影子 sn-p,与你的不同:
fn main() {
let x = a();
let x = b();
}
步骤,按顺序:
a()创建一个值,绑定到x
b()创建一个值,绑定到x
b() 创建的值被丢弃a() 创建的值被丢弃请注意,x 被重新绑定这一事实不会影响之前绑定的值的生命周期。
从技术上讲,它的行为与 b() 的结果绑定到 y 完全相同,唯一的例外是之前的 x 绑定在 y 在范围内时不可访问。
现在,可变的 sn-p:
fn main() {
let mut x = a();
x = b();
}
步骤,按顺序:
a()创建一个值,绑定到x
b() 创建一个值,该值绑定到x,之前的值(由a() 创建)被删除b() 创建的值被丢弃再一次,访问前一个值是不可能的,但是在使用遮蔽时暂时是不可能的(如果在较小的范围内进行遮蔽),使用赋值是永远不可能的,因为值被删除了。
【讨论】:
x = y; 函数 fn main() { let x; { let y = hello(); x = y; } println!("{}", x); } 中的 let x = y; 不应该是 let x = y; 另外,您能否向像我这样的新手澄清为什么“b”创造的价值在“a”创造的价值之前被丢弃。试图确保我完全吸收这个。
x = y;。 let x; 是一种提前声明绑定而不实际绑定它的方法(还)。这在这里用于将值分配给y escape 其范围。 (2) 在词法作用域结束时,变量按其创建的相反顺序被销毁;这是必要的,以便变量可以安全地引用在它之前声明的变量。例如,考虑let vec = vec!(1, 2); let x = &vec[0];:如果vec首先被销毁,x将指向释放的内存!
fn main() { let x = a(); let x = b(); }中,a()创建的值可以一直持续到进程结束,而其他地方根本没有用到。
let x = a(); let y = b(); 而不是使用阴影重新绑定x 两次。
我自己找到了一个答案:阴影可以改变变量类型。
let x = get_some_string();
let x = x.smart_parse_int();
【讨论】:
let mut foo = Foo::new(); /* build foo */ let foo = foo; // make foo immutable.
let foo = { let mut foo = Foo::new(); ...; foo };