仅含原始类型的Rust结构体仍会被移动?编译疑问解析
问题解答
你忽略的核心要点是:结构体本身不会自动派生Copy trait,哪怕它的所有字段都实现了Copy。
Rust中,只有当一个类型的所有字段都实现了Copy,并且该类型显式派生(或手动实现)了Copy trait时,它才具备可复制性。你的Rectangle结构体虽然字段都是默认实现Copy的u32,但你只派生了Debug,没有派生Copy,所以调用area(rect1)时会触发移动语义——rect1的所有权被转移到area函数中,函数执行完毕后rect1被销毁,后续println中再访问rect1.width和rect1.height自然会编译报错。
两种修复方式
1. 为结构体派生Copy和Clone trait
Copy trait依赖Clone,所以需要一起派生:
#[derive(Debug, Copy, Clone)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; let a = area(rect1); // 此时会复制rect1,而非移动 println!("{} * {} = {}", rect1.width, rect1.height, a); // 可正常访问rect1 } fn area(rectangle: Rectangle) -> u32 { rectangle.width * rectangle.height }
2. 使用引用传递避免移动
如果不想让结构体实现Copy,可以修改area函数参数为引用类型,仅借用所有权而非转移:
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; let a = area(&rect1); // 传递rect1的引用 println!("{} * {} = {}", rect1.width, rect1.height, a); // rect1所有权仍在main中,可正常访问 } fn area(rectangle: &Rectangle) -> u32 { rectangle.width * rectangle.height // 引用可直接访问字段 }
内容的提问来源于stack exchange,提问作者codeTIT4N
相关产品推荐
相关产品推荐

