为什么我不能阻止一个盒子?
Why can't I hold back a box?
考虑以下代码 (on playground):
// calling this function move the ownership of nbr to is_even
// at the end of the function is_even doesn't give the ownership back
fn is_even(nbr: Box<i32>) -> bool {
*nbr % 2 == 0
}
fn main() {
let integer = Box::new(42);
if is_even(integer) {
print!("is even ");
}
println!("{}", integer);
}
我收到以下错误消息:
example.rs:10:17: 10:24 error: use of moved value: `integer` [E0382]
example.rs:10 println!("{}", integer);
example.rs:7:13: 7:20 note: `integer` moved here because it has type `Box<i32>`, which is non-copyable
example.rs:7 if is_even(integer) {
我不明白为什么。好的,当我调用 is_even
时,我将所有权授予该函数,但在 is_even
结束时该函数不再需要所有权。它是所有权的不可变(只读)转移,因此我们确定当 main
阻止 integer
时它不会被删除 -> 似乎可以安全地使用它。
还是出现这个错误。为什么以及解决方法是什么?
如果您想保留您的盒子的所有权,那么您必须is_even
借用它,而不是取得它的所有权。这是您的代码的工作版本:
// calling this function move the ownership of nbr to is_even
// at the end of the function is_even doesn't give the ownership back
fn is_even(nbr: &Box<i32>) -> bool {
**nbr % 2 == 0
}
fn main() {
let integer = Box::new(42);
if is_even(&integer) {
print!("is even ");
}
println!("{}", integer);
}
请注意,is_even
现在需要对 Box 的引用(使用 &
),并且我们必须在我们使用时传递引用(再次使用 &
)调用函数。最后,该函数现在对引用而不是值进行操作,因此我们需要添加另一个 *
以取消对它的引用,然后才能对它进行操作。
但是,避免对拥有其内容的值(例如 String
或 Vec
或 Box
)使用不可变引用是一个很好的经验法则。该函数可以重写如下:
fn is_even(nbr: &i32) -> bool {
*nbr % 2 == 0
}
这适用于 任何 对整数的引用,而不仅仅是 Box
es.
中的整数
when I call is_even
, I give the ownership to this function
没错。您已转让所有权。您不再拥有它,该功能将执行它想要的操作。在这种情况下,它会释放内存,因此您肯定在调用后无法使用它。
that function doesn't need the ownership any more
这就是它被删除的原因。
It is a immutable (read only) transfer of ownership
那不存在。您完全转让所有权,没有半途。
so we are sure it is not deleted
实际上,我们确定它已被释放,这是一件非常好的事情。 Rust 为我们管理,所以你永远不必问 "who should free this?"
那你是怎么解决的呢?很简单:传递对内部值的引用,而不是整个框。此 借用 值(可变与否,由您决定)并且所有权不会转移。
fn is_even(nbr: &i32) -> bool { ... }
考虑以下代码 (on playground):
// calling this function move the ownership of nbr to is_even
// at the end of the function is_even doesn't give the ownership back
fn is_even(nbr: Box<i32>) -> bool {
*nbr % 2 == 0
}
fn main() {
let integer = Box::new(42);
if is_even(integer) {
print!("is even ");
}
println!("{}", integer);
}
我收到以下错误消息:
example.rs:10:17: 10:24 error: use of moved value: `integer` [E0382]
example.rs:10 println!("{}", integer);
example.rs:7:13: 7:20 note: `integer` moved here because it has type `Box<i32>`, which is non-copyable
example.rs:7 if is_even(integer) {
我不明白为什么。好的,当我调用 is_even
时,我将所有权授予该函数,但在 is_even
结束时该函数不再需要所有权。它是所有权的不可变(只读)转移,因此我们确定当 main
阻止 integer
时它不会被删除 -> 似乎可以安全地使用它。
还是出现这个错误。为什么以及解决方法是什么?
如果您想保留您的盒子的所有权,那么您必须is_even
借用它,而不是取得它的所有权。这是您的代码的工作版本:
// calling this function move the ownership of nbr to is_even
// at the end of the function is_even doesn't give the ownership back
fn is_even(nbr: &Box<i32>) -> bool {
**nbr % 2 == 0
}
fn main() {
let integer = Box::new(42);
if is_even(&integer) {
print!("is even ");
}
println!("{}", integer);
}
请注意,is_even
现在需要对 Box 的引用(使用 &
),并且我们必须在我们使用时传递引用(再次使用 &
)调用函数。最后,该函数现在对引用而不是值进行操作,因此我们需要添加另一个 *
以取消对它的引用,然后才能对它进行操作。
但是,避免对拥有其内容的值(例如 String
或 Vec
或 Box
)使用不可变引用是一个很好的经验法则。该函数可以重写如下:
fn is_even(nbr: &i32) -> bool {
*nbr % 2 == 0
}
这适用于 任何 对整数的引用,而不仅仅是 Box
es.
when I call
is_even
, I give the ownership to this function
没错。您已转让所有权。您不再拥有它,该功能将执行它想要的操作。在这种情况下,它会释放内存,因此您肯定在调用后无法使用它。
that function doesn't need the ownership any more
这就是它被删除的原因。
It is a immutable (read only) transfer of ownership
那不存在。您完全转让所有权,没有半途。
so we are sure it is not deleted
实际上,我们确定它已被释放,这是一件非常好的事情。 Rust 为我们管理,所以你永远不必问 "who should free this?"
那你是怎么解决的呢?很简单:传递对内部值的引用,而不是整个框。此 借用 值(可变与否,由您决定)并且所有权不会转移。
fn is_even(nbr: &i32) -> bool { ... }