我正在尝试daily programmer problem来重新排列参数列表并输出它们。
我不确定这是否是正确的方法,但这听起来是个好主意:从args向量中删除元素,使其不会重复,并将其插入到结果向量中。
extern crate rand;
use std::io;
use std::cmp::Ordering;
use std::env;
use rand::Rng;
fn main() {
let mut args: Vec<_> = env::args().collect();
let mut result: Vec<_> = Vec::with_capacity(args.capacity());
if args.len() > 1 {
println!("There are(is) {} argument(s)", args.len() - 1)
}
for x in args.iter().skip(1) {
let mut n = rand::thread_rng().gen_range(1, args.len());
result.push(&args.swap_remove(n));
}
for y in result.iter() {
println!("{}", y);
}
}
我收到错误:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:18:42
|
18 | result.push(&args.swap_remove(n));
| ------------------- ^ temporary value dropped here while still borrowed
| |
| temporary value created here
...
24 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
答案 0 :(得分:6)
让我们从一个较小的例子开始。这称为MCVE,对于您作为程序员和我们回答您的问题非常有价值。此外,它可以在Rust Playground上运行,这很方便。
fn main() {
let mut args = vec!["a".to_string()];
let mut result = vec![];
for x in args.iter() {
let n = args.len() - 1; // Pretend this is a random index
result.push(&args.swap_remove(n));
}
for y in result.iter() {
println!("{}", y);
}
}
出现问题是因为当您致电swap_remove
时,项目已移动从向量中移出并提供给您 - 所有权已转移。然后,您可以对该项进行引用,并尝试将该引用存储在result
向量中。问题是在循环迭代结束后该项被删除,因为没有任何东西拥有它。如果您被允许使用该引用,那么它将是悬空引用,指向无效内存。使用该引用可能会导致崩溃,因此Rust会阻止它。
立即修复是不参考,而是将所有权从一个向量转移到另一个向量。类似的东西:
for x in args.iter() {
let n = args.len() - 1;
result.push(args.swap_remove(n));
}
问题在于你会得到cannot borrow `args` as mutable because it is also borrowed as immutable
。查看args.iter
?这会创建一个引用向量的迭代器。如果您更改了向量,那么迭代器将变为无效,并允许访问可能不存在的项目,Rust可能阻止的另一个潜在崩溃。
我没有声称这是一个很好的方法,但是有一个解决方案是在仍有项目的情况下进行迭代:
while args.len() > 0 {
let n = args.len() - 1;
result.push(args.swap_remove(n));
}
我使用shuffle
:
extern crate rand;
use std::env;
use rand::Rng;
fn main() {
let mut args: Vec<_> = env::args().skip(1).collect();
rand::thread_rng().shuffle(&mut args);
for y in &args {
println!("{}", y);
}
}