Rust Option类型向量处理编译报错E0507原因及遍历疑问
关于Rust中Vec<Option>遍历报错的原因解析
先看这段编译失败的代码,功能是提取Vec<Option<T>>里的Some(T)元素到另一个Vec<T>,同时统计None的数量:
pub fn process_options<T>(in_refs:& mut Vec<T>,ivals:Vec<Option<T>>) -> i32 { let mut nones = 0; for int in 0..ivals.len() { if let None = ivals[int] { nones += 1; } else { in_refs.push(ivals[int].unwrap()); } } return nones; }
编译时会报如下错误:
error[E0507]: cannot move out of index of `Vec<Option<T>>` --> src/functions.rs:40:26 | 40 | in_refs.push(ivals[int].unwrap()); | ^^^^^^^^^^ -------- value moved due to this method call | | | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | move occurs because value has type `Option<T>`, which does not implement the `Copy` trait | note: this function takes ownership of the receiver `self`, which moves value --> /Users/yunfeichen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/option.rs:772:25 | 772 | pub const fn unwrap(self) -> T {
改用遍历ivals本身的代码就能正常编译:
pub fn process_options<T>(in_refs:& mut Vec<T>,ivals:Vec<Option<T>>) -> i32 { let mut nones = 0; for element in ivals{ if let None = element { nones += 1; } else { in_refs.push(element.unwrap()); } } return nones; }
错误原因解析
- 索引访问的问题:用
ivals[int]访问Vec元素时,由于Option<T>没实现Copytrait,Rust会尝试把这个Option<T>从Vec里移出来。第一次if let None = ivals[int]已经动了这个位置的元素,第二次ivals[int].unwrap()又要移同一个位置的元素——这违反了Rust的所有权规则:同一个值不能被移动两次,而且移动后原位置的元素会失效,Vec的结构也会被破坏,所以编译器直接报错阻止。 - 遍历所有权转移的合理性:
for element in ivals这种遍历是直接把ivals里每个Option<T>的所有权转到element变量上。因为函数参数ivals本身就拥有整个Vec的所有权(不是引用),逐个转移元素所有权完全合法,每个element只会被处理一次,调用unwrap()时也是操作自己拥有所有权的变量,完全符合Rust的规则,所以能正常编译。
内容的提问来源于stack exchange,提问作者chen
相关产品推荐
相关产品推荐

