作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试 daily programmer problem打乱参数列表并输出它们。
我不确定这是否是正确的方法,但它听起来是个好主意:从 args 向量中删除该元素以使其不会重复,然后将其插入到结果向量中。
extern crate rand; // 0.7.3
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[E0716]: temporary value dropped while borrowed
--> src/main.rs:18:22
|
18 | result.push(&args.swap_remove(n));
| ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
...
21 | for y in result.iter() {
| ------ borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
老编译器说:
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
最佳答案
让我们从一个较小的例子开始。这称为 Minimal, Reproducible Example ,对于您作为程序员和我们回答您的问题都非常有值(value)。此外,它可以在 Rust Playground 上运行, 这很方便。
fn main() {
let mut args = vec!["a".to_string()];
let mut result = vec![];
for _ 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 _ in args.iter() {
let n = args.len() - 1; // Pretend this is a random index
result.push(args.swap_remove(n));
}
这样做的问题是你会得到
error[E0502]: cannot borrow `args` as mutable because it is also borrowed as immutable
--> src/main.rs:7:21
|
5 | for _ in args.iter() {
| -----------
| |
| immutable borrow occurs here
| immutable borrow later used here
6 | let n = args.len() - 1;
7 | result.push(args.swap_remove(n));
| ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
看到args.iter
了吗?这将创建一个引用向量的迭代器。如果您更改了向量,那么迭代器将变得无效,并允许访问可能不存在的项目,这是 Rust 防止的另一个潜在崩溃。
我并不是说这是一个好方法,但一种解决方案是在仍有项目时进行迭代:
while !args.is_empty() {
let n = args.len() - 1; // Pretend this is a random index
result.push(args.swap_remove(n));
}
我会使用 shuffle
解决整个问题:
use rand::seq::SliceRandom; // 0.8.3
use std::env;
fn main() {
let mut args: Vec<_> = env::args().skip(1).collect();
args.shuffle(&mut rand::thread_rng());
for y in &args {
println!("{}", y);
}
}
关于list - 插入向量时为 "Borrowed Value Does Not Live Long Enough",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31661713/
我是一名优秀的程序员,十分优秀!