有没有办法告诉编译器我正在循环管理变量的所有权?
Is there a way to tell the compiler that I am managing ownership of a variable in a loop?
我试图在一个循环中将一个变量的所有权赋予一个函数,我有自己的布尔值来确保它只发生一次,但是编译器告诉我该值在上一次迭代中被移动了。
这是一个例子:
fn take_ownership(a: String) {
println!("{}", a);
}
fn main() {
let mut a = true;
let hello = "Hello".to_string();
for _ in 0..5 {
if a {
a = false;
take_ownership(hello);
}
}
}
使用这段代码,编译器告诉我:
error[E0382]: use of moved value: `hello`
--> src/main.rs:12:28
|
12 | take_ownership(hello);
| ^^^^^ value moved here in previous iteration of loop
有没有办法告诉编译器"it's ok, I will handle it"?我不想使用引用 (&
).
告诉编译器 "It's OK, I will handle it" 的常用方法是使用 unsafe
。您 可以 在这里使用 unsafe
以及一些深奥的 ptr
魔法,但这将非常脆弱并且难以证明正确。
但是,使用 Option
:
是安全且容易的事情
let mut a = Some("Hello".to_string());
for _ in 0..5 {
if let Some(hello) = a.take() {
take_ownership(hello);
}
}
原来,a
和 hello
之间没有类型级别的关系,所以编译器不能确定 hello
只移动了一次。 Option
将不变量 "there might be a thing here, or it might be gone" 编码为类型,因此编译器可以知道 take_ownership
仅在有内容传递给它时才被调用。
.take()
is a method that replaces a
with None
, returning the contents (if any). Because this method does not consume the Option
, it's fine to call it multiple times in a loop. 是一个相关问题。
我试图在一个循环中将一个变量的所有权赋予一个函数,我有自己的布尔值来确保它只发生一次,但是编译器告诉我该值在上一次迭代中被移动了。
这是一个例子:
fn take_ownership(a: String) {
println!("{}", a);
}
fn main() {
let mut a = true;
let hello = "Hello".to_string();
for _ in 0..5 {
if a {
a = false;
take_ownership(hello);
}
}
}
使用这段代码,编译器告诉我:
error[E0382]: use of moved value: `hello`
--> src/main.rs:12:28
|
12 | take_ownership(hello);
| ^^^^^ value moved here in previous iteration of loop
有没有办法告诉编译器"it's ok, I will handle it"?我不想使用引用 (&
).
告诉编译器 "It's OK, I will handle it" 的常用方法是使用 unsafe
。您 可以 在这里使用 unsafe
以及一些深奥的 ptr
魔法,但这将非常脆弱并且难以证明正确。
但是,使用 Option
:
let mut a = Some("Hello".to_string());
for _ in 0..5 {
if let Some(hello) = a.take() {
take_ownership(hello);
}
}
原来,a
和 hello
之间没有类型级别的关系,所以编译器不能确定 hello
只移动了一次。 Option
将不变量 "there might be a thing here, or it might be gone" 编码为类型,因此编译器可以知道 take_ownership
仅在有内容传递给它时才被调用。
.take()
is a method that replaces a
with None
, returning the contents (if any). Because this method does not consume the Option
, it's fine to call it multiple times in a loop.