“cannot move out of index of” 是什么意思?(涉及IT技术)

97

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

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`

或者在 Rust 的后续版本中:

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,它就可以编译了,但我不明白正在发生什么。有人能解释一下"indexed content"是什么意思吗?

2个回答

104

使用索引运算符([]),您可以获取索引位置上的实际对象。您不会得到引用、指针或副本。由于您试图将该对象与let绑定,Rust 立即尝试移动(如果实现了Copy trait,则为复制)。

在您的示例中,env::args()是一个 String 迭代器,然后被收集到一个 Vec<String> 中。这是一个拥有所有权的字符串向量,而拥有所有权的字符串不会自动复制。

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

use std::env;

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

隐式移出一个 Vec 是不允许的,因为这会使其处于无效状态——一个元素被移出了,而其他元素没有。如果您有一个可变的 Vec,则可以使用像Vec::remove这样的方法来取出单个值:

use std::env;

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

另请参见:


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

use std::env;

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

7
如果我拥有这个数组,并想要获取数组中的某个单独值的所有权(同时消耗掉整个数组的所有权),该怎么办? - Thayne
4
如果它是一个 Vec,你可以使用 remove 方法。否则,你可以使用 mem::replace 将值替换为虚拟值。 - oli_obk
vec.into_iter().nth(1).expect("Missing element") 的作用是什么? - Tomáš Dvořák
一条注解:Index 特质看上去应该返回一个引用,但正如这个答案所指出的那样,实际上并不是这样。另请参阅 https://dev59.com/m14c5IYBdhLWcg3weaT8 - nnnmmm
Rust 立即尝试移动 - 为什么它要尝试移动而不是传递这个 String 的所有权呢? - Anatoly Bugakov

5
已经有一位答主给出了解决方案。作为补充,我想从语义层面解释这个问题。
规则是:借用的值不能被搬走。请参见:E0507[]运算符来自于Index trait,其函数签名为:
fn index(&self, index: I) -> &<Vec<T, A> as Index<I>>::Output

正如您所看到的,它返回一个引用,而不是拥有该值。将其移出会违反上述规则。


1
以下是有关编程的内容,请将其从英语翻译成中文。请仅返回已翻译的文本,不要进行解释。 - chailong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接