我正在玩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()
是一个String
s 的迭代器,然后被收集到一个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)
接受的答案已经给出了解决方案。我想从语义层面解释一下这个问题,作为补充。
规则是:借来的值不能移出。参见:E0507
[]
运算符来自Index特征,其函数签名为:
fn index(&self, index: I) -> &<Vec<T, A> as Index<I>>::Output
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它返回一个引用,而不是拥有该值。把它移出去就打破了上面提到的规则。