问题描述
如果在创建绑定时使用自动类型推导,如何知道绑定的类型?如果右边的表达式是借用(比如 let x = &5;
),它是值还是借用?如果我重新分配借用或价值会怎样?
How could know the type of a binding if I use auto type deduction when creating a binding? what if the expression on the right side is a borrow(like let x = &5;
), will it be value or a borrow? What will happen if I re-assign a borrow or a value?
只是为了检查,如果我使用 let mut x: &mut T = &mut T{};
或 let mut x:& ,我可以重新分配借用;T = &T{};
,对吧?
Just for check, I do can re-assign a borrow if I use let mut x: &mut T = &mut T{};
or let mut x:&T = & T{};
, right?
推荐答案
我觉得 binding 和 assigning 之间有些混淆:
I sense some confusion between binding and assigning:
- 绑定引入了一个新变量,并将其与一个值相关联,
- 赋值会用另一个值覆盖一个值.
- Binding introduces a new variable, and associates it to a value,
- Assigning overwrites a value with another.
这可以用简单的两行来说明:
This can be illustrated in two simple lines:
let mut x = 5; // Binding
x = 10; // Assigning
绑定可能出现在 Rust 中的多个位置:
A binding may appear in multiple places in Rust:
let
语句,if let
/while let
条件,match
表达式中的案例,- 甚至在
for
表达式中,在in
的左侧.
let
statements,if let
/while let
conditions,- cases in a
match
expression, - and even in a
for
expression, on the left side ofin
.
只要有绑定,Rust 的语法也允许模式匹配:
Whenever there is a binding, Rust's grammar also allows pattern matching:
- 在
let
语句和for
表达式的情况下,模式必须是无可辩驳的, - 在
if let
、while let
和match
的情况下,模式可能无法匹配.
- in the case of
let
statements andfor
expressions, the patterns must be irrefutable, - in the case of
if let
,while let
andmatch
cases, the patterns may fail to match.
模式匹配意味着绑定引入的变量类型因绑定方式不同而不同:
Pattern matching means that the type of the variable introduced by the binding differs based on how the binding is made:
let x = &5; // x: &i32
let &y = &5; // y: i32
赋值总是需要使用赋值运算符=
.
Assigning always requires using =
, the assignment operator.
赋值时,前一个值被覆盖,如果实现了Drop
,则对其调用drop
.
When assigning, the former value is overwritten, and drop
is called on it if it implements Drop
.
let mut x = 5;
x = 6;
// Now x == 6, drop was not called because it's a i32.
let mut s = String::from("Hello, World!");
s = String::from("Hello, 神秘德里克!");
// Now s == "Hello, 神秘德里克!", drop was called because it's a String.
被覆盖的值可能很简单,如整数或浮点数、更复杂的struct
或enum
,或引用.
The value that is overwritten may be as simple as an integer or float, a more involved struct
or enum
, or a reference.
let mut r = &5;
r = &6;
// Now r points to 6, drop was not called as it's a reference.
覆盖引用不会覆盖引用指向的值,而是覆盖引用本身.原始值仍然存在,准备好后将被删除.
Overwriting a reference does not overwrite the value pointed to by the reference, but the reference itself. The original value still lives on, and will be dropped when it's ready.
要覆盖指向的值,需要使用*
,解引用运算符:
To overwrite the pointed to value, one needs to use *
, the dereference operator:
let mut x = 5;
let r = &mut x;
*r = 6;
// r still points to x, and now x = 6.
如果解引用值的类型需要它,drop
将被调用:
If the type of the dereferenced value requires it, drop
will be called:
let mut s = String::from("Hello, World!");
let r = &mut s;
*r = String::from("Hello, 神秘德里克!");
// r still points to s, and now s = "Hello, 神秘德里克!".
我邀请你去游乐场玩玩,你可以开始从这里:
I invite you to use to playground to and toy around, you can start from here:
fn main() {
let mut s = String::from("Hello, World!");
{
let r = &mut s;
*r = String::from("Hello, 神秘德里克!");
}
println!("{}", s);
}
希望现在事情应该更清楚了,所以让我们检查一下您的样本.
Hopefully, things should be a little clearer now, so let's check your samples.
let x = &5;
x
是对 i32 (&i32
) 的引用.发生的事情是编译器会引入一个临时存储5
,然后借用这个临时.
x
is a reference to i32 (&i32
). What happens is that the compiler will introduce a temporary in which 5
is stored, and then borrow this temporary.
let mut x: &mut T = T{};
不可能.T{}
的类型是 T
而不是 &mut T
,所以编译失败.您可以将其更改为 let mut x: &mut T = &mut T{};
.
Is impossible. The type of T{}
is T
not &mut T
, so this fails to compile. You could change it to let mut x: &mut T = &mut T{};
.
你的最后一个例子是相似的.
And your last example is similar.
这篇关于Rust 中赋值的语义是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!