为何函数未获取Option<T>参数的所有权?变量移动规则疑问
为什么函数调用后原变量没被移动?
先看你的代码:
fn main() { let tested = Some(5); testoption(tested); println!("the tested is {}", tested.unwrap()); } fn testoption(p: Option<i32>) { println!("the argument is {}", p.unwrap()); }
你觉得会触发移动但实际没有,核心原因是你的Option<i32>实现了Copy trait——实现这个trait的类型,在作为函数参数传递、赋值等场景下,会自动进行值复制,而不是转移所有权(移动),所以原变量依然可以正常使用。
哪些类型调用函数后不会被移动(即自动复制)?
- 原生基本类型:比如
i32、u64、f32、bool、char等,Rust默认给这些类型实现了Copy。 - 由Copy类型组合的复合类型:
- 元组:比如
(i32, bool),只要所有元素都是Copy类型,元组自动实现Copy; - 结构体:如果结构体的所有字段都是Copy类型,并且你没有手动禁止,通过
#[derive(Copy, Clone)]可以让结构体实现Copy; - 标准库泛型类型:比如
Option<T>、Result<T, E>,只要泛型参数T(和E)是Copy类型,这些泛型类型也会自动实现Copy——你的例子里i32是Copy,所以Option<i32>也自动成了Copy类型。
- 元组:比如
- 手动实现Copy的自定义类型:只要自定义类型的所有成员都实现了Copy,你就可以通过
#[derive(Copy, Clone)]或者手动实现Copytrait,让它具备自动复制的特性。
反过来,如果类型没有实现Copy(比如String、Vec这类拥有堆内存的类型),传递给函数时就会触发移动,原变量之后就不能再被使用了——比如把你的例子改成Some(String::from("hello")),再运行就会编译报错,因为Option<String>没实现Copy,传递时移动了所有权。
内容的提问来源于stack exchange,提问作者passinger
相关产品推荐
相关产品推荐

