“不能走出指数”是什么意思?

我正在使用 生锈了,并试图通过以下代码访问第一个命令行参数:

use std::env;


fn main() {
let args: Vec<_> = env::args().collect();
let dir = args[1];
}

我得到了这个错误:

error[E0507]: cannot move out of indexed content
--> src/main.rs:5:15
|
5 |     let dir = args[1];
|         ---   ^^^^^^^ cannot move out of indexed content
|         |
|         hint: to prevent move, use `ref dir` or `ref mut dir`

或者在《铁锈》的后期版本中:

error[E0507]: cannot move out of index of `std::vec::Vec<std::string::String>`
--> src/main.rs:5:15
|
5 |     let dir = args[1];
|               ^^^^^^^
|               |
|               move occurs because value has type `std::string::String`, which does not implement the `Copy` trait
|               help: consider borrowing here: `&args[1]`

如果我把它改为 let ref dir,它会编译,但我不理解发生了什么。有人能解释一下“索引内容”是什么意思吗?

30021 次浏览

When you use an index operator ([]) you get the actual object at index location. You do not get a reference, pointer or copy. Since you try to bind that object with a let binding, Rust immediately tries to move (or copy, if the Copy trait is implemented).

In your example, env::args() is an iterator of Strings which is then collected into a Vec<String>. This is an owned vector of owned strings, and owned strings are not automatically copyable.

You can use a let ref binding, but the more idiomatic alternative is to take a reference to the indexed object (note the & symbol):

use std::env;


fn main() {
let args: Vec<_> = env::args().collect();
let ref dir = &args[1];
//            ^
}

Implicitly moving out of a Vec is not allowed as it would leave it in an invalid state — one element is moved out, the others are not. If you have a mutable Vec, you can use a method like Vec::remove to take a single value out:

use std::env;


fn main() {
let mut args: Vec<_> = env::args().collect();
let dir = args.remove(1);
}

See also:


For your particular problem, you can also just use Iterator::nth:

use std::env;


fn main() {
let dir = env::args().nth(1).expect("Missing argument");
}

The accepted answer has already given the solution. I would like to explain this problem on a semantic level as a complement.

The rule is: A borrowed value can't be move out. See this: E0507

[] operator came from the Index trait, whose function signature is:

fn index(&self, index: I) -> &<Vec<T, A> as Index<I>>::Output

As you can see, it return a reference, not own the value. Moving it out break the rule mentioned above.