Rust 借用检查器在 if 语句中抛出错误
Rust borrow checker throwing error in if statement
我正在 运行 通过一些 LeetCode 挑战来加深我对 Rust 的理解。我正在尝试编写以下程序,它接受 i32
输入,将其转换为 String
,反转数字,然后 returns 返回 i32
数字。
在负数的情况下,例如-132
,当数字反转时,连字符必须从堆栈中弹出:-132
-> 231-
-> 231
.
我写了下面的代码,但我遇到了借用检查器,有人能帮忙吗?
impl Solution {
pub fn reverse(x: i32) -> i32 {
if(x == 0){
return x;
}
let reversed : std::iter::Rev<std::str::Chars> = x.to_string().chars().rev();
if reversed.last().unwrap() == '-' { //error occurs here
return reversed.collect::<String>()[0..reversed.count()].parse::<i32>().unwrap();
} else {
return reversed.collect::<String>().parse::<i32>().unwrap();
}
}
}
Line 6, Char 61: temporary value dropped while borrowed (solution.rs)
|
6 | let reversed : &std::iter::Rev<std::str::Chars> = &x.to_string().chars().rev();
| ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
7 | if reversed.last().unwrap() == '-' {
| -------- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
Line 7, Char 12: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
7 | if reversed.last().unwrap() == '-' {
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
Line 8, Char 20: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
8 | return reversed.collect::<String>()[0..reversed.count()].parse::<i32>().unwrap();
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
Line 8, Char 52: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
8 | return reversed.collect::<String>()[0..reversed.count()].parse::<i32>().unwrap();
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
Line 10, Char 20: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
10 | return reversed.collect::<String>().parse::<i32>().unwrap();
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
这是在 playground
中重现的错误
为什么不在将 x
转换为 String
之前取其绝对值,这样您就不必处理连字符边缘情况?
fn reverse(x: i32) -> i32 {
x.abs()
.to_string()
.chars()
.rev()
.collect::<String>()
.parse::<i32>()
.unwrap()
}
fn main() {
assert_eq!(reverse(1234567), 7654321);
assert_eq!(reverse(-1234567), 7654321);
}
即使我们将输入作为 String
并且必须处理连字符,最惯用的解决方案是 filter()
输出:
fn reverse(x: String) -> i32 {
x.chars()
.filter(|&c| c != '-')
.rev()
.collect::<String>()
.parse::<i32>()
.unwrap()
}
fn main() {
assert_eq!(reverse(1234567.to_string()), 7654321);
assert_eq!(reverse((-1234567).to_string()), 7654321);
}
此处重现原始错误 playground
这里有一个接近于你修复错误的方法的解决方案:
fn reverse(x: i32) -> i32 {
if x == 0 {
return x;
}
let mut reversed:String = x.to_string().chars().rev().collect::<String>();
if reversed.chars().last() == Some('-') {
reversed.pop();
}
reversed.parse::<i32>().unwrap()
}
工作版本:playground
这个 很好地解释了原因。在这个问题的上下文中:
x.to_string().chars().rev();
// ^ ^
// String <- &str
to_string
returns a String
,但是代码在这个语句之后没有引用那个 String
,所以它需要释放 String
,但是迭代器引用了 chars()
中的 &str
,然后它变成了对不再存在的东西的引用。通过将 reversed
的类型更改为 String
并使用 collect
然后 Rust 可以将新数据绑定到局部变量并且不必在语句末尾删除它。
LeetCode 挑战是否强加了 int→string→int 的转换?我会直接在整数上做:
fn reverse (x: i32) -> i32 {
let mut x = x.abs();
let mut y = 0;
while x != 0 {
y = y*10 + x%10;
x = x/10;
}
return y;
}
我正在 运行 通过一些 LeetCode 挑战来加深我对 Rust 的理解。我正在尝试编写以下程序,它接受 i32
输入,将其转换为 String
,反转数字,然后 returns 返回 i32
数字。
在负数的情况下,例如-132
,当数字反转时,连字符必须从堆栈中弹出:-132
-> 231-
-> 231
.
我写了下面的代码,但我遇到了借用检查器,有人能帮忙吗?
impl Solution {
pub fn reverse(x: i32) -> i32 {
if(x == 0){
return x;
}
let reversed : std::iter::Rev<std::str::Chars> = x.to_string().chars().rev();
if reversed.last().unwrap() == '-' { //error occurs here
return reversed.collect::<String>()[0..reversed.count()].parse::<i32>().unwrap();
} else {
return reversed.collect::<String>().parse::<i32>().unwrap();
}
}
}
Line 6, Char 61: temporary value dropped while borrowed (solution.rs)
|
6 | let reversed : &std::iter::Rev<std::str::Chars> = &x.to_string().chars().rev();
| ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
7 | if reversed.last().unwrap() == '-' {
| -------- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
Line 7, Char 12: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
7 | if reversed.last().unwrap() == '-' {
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
Line 8, Char 20: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
8 | return reversed.collect::<String>()[0..reversed.count()].parse::<i32>().unwrap();
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
Line 8, Char 52: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
8 | return reversed.collect::<String>()[0..reversed.count()].parse::<i32>().unwrap();
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
Line 10, Char 20: cannot move out of `*reversed` which is behind a shared reference (solution.rs)
|
10 | return reversed.collect::<String>().parse::<i32>().unwrap();
| ^^^^^^^^ move occurs because `*reversed` has type `std::iter::Rev<std::str::Chars<'_>>`, which does not implement the `Copy` trait
这是在 playground
中重现的错误为什么不在将 x
转换为 String
之前取其绝对值,这样您就不必处理连字符边缘情况?
fn reverse(x: i32) -> i32 {
x.abs()
.to_string()
.chars()
.rev()
.collect::<String>()
.parse::<i32>()
.unwrap()
}
fn main() {
assert_eq!(reverse(1234567), 7654321);
assert_eq!(reverse(-1234567), 7654321);
}
即使我们将输入作为 String
并且必须处理连字符,最惯用的解决方案是 filter()
输出:
fn reverse(x: String) -> i32 {
x.chars()
.filter(|&c| c != '-')
.rev()
.collect::<String>()
.parse::<i32>()
.unwrap()
}
fn main() {
assert_eq!(reverse(1234567.to_string()), 7654321);
assert_eq!(reverse((-1234567).to_string()), 7654321);
}
此处重现原始错误 playground
这里有一个接近于你修复错误的方法的解决方案:
fn reverse(x: i32) -> i32 {
if x == 0 {
return x;
}
let mut reversed:String = x.to_string().chars().rev().collect::<String>();
if reversed.chars().last() == Some('-') {
reversed.pop();
}
reversed.parse::<i32>().unwrap()
}
工作版本:playground
这个
x.to_string().chars().rev();
// ^ ^
// String <- &str
to_string
returns a String
,但是代码在这个语句之后没有引用那个 String
,所以它需要释放 String
,但是迭代器引用了 chars()
中的 &str
,然后它变成了对不再存在的东西的引用。通过将 reversed
的类型更改为 String
并使用 collect
然后 Rust 可以将新数据绑定到局部变量并且不必在语句末尾删除它。
LeetCode 挑战是否强加了 int→string→int 的转换?我会直接在整数上做:
fn reverse (x: i32) -> i32 {
let mut x = x.abs();
let mut y = 0;
while x != 0 {
y = y*10 + x%10;
x = x/10;
}
return y;
}