"无法摆脱索引内容"是什么意思?

Ror*_*ory 54 rust

我正在玩Rust,我正在尝试使用以下代码访问第一个命令行参数:

use std::env;

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

我收到这个错误:

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`
Run Code Online (Sandbox Code Playgroud)

如果我改成它let ref dir,它会编译,但我不知道发生了什么.有人可以解释一下"索引内容"是什么意思吗?

oli*_*obk 55

当您使用索引运算符([])时,您将获得索引位置的实际对象.您没有获得引用,指针或副本.由于您尝试使用绑定绑定该对象let,因此Rust会立即尝试移动(或复制,如果Copy实现了特征).

在你的例子中,env::args()是一个Strings 的迭代器,然后被收集到一个Vec<String>.这是拥有的字符串的拥有向量,拥有的字符串不能自动复制.

您可以使用let ref绑定,但更惯用的替代方法是引用索引对象(请注意&符号):

use std::env;

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

Vec不允许隐式移出a,因为它会使其处于无效状态 - 一个元素被移出,其他元素则不移出.如果你有一个mutable Vec,你可以使用一个方法Vec::remove来取出一个值:

use std::env;

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

对于您的特定问题,您还可以使用Iterator::nth:

use std::env;

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

  • 如果我拥有该数组,并希望获得数组中单个值的所有权(并使用该数组的所有权),该怎么办? (4认同)
  • 如果它是`Vec`你可以使用`remove`方法,否则你可以用虚拟值`mem :: replace`这个值. (3认同)

wah*_*aha 5

接受的答案已经给出了解决方案。我想从语义层面解释一下这个问题,作为补充。

规则是:借来的值不能移出。参见:E0507

[]运算符来自Index特征,其函数签名为:

fn index(&self, index: I) -> &<Vec<T, A> as Index<I>>::Output
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它返回一个引用,而不是拥有该值。把它移出去就打破了上面提到的规则。