rust基本类型所有权已经实现了copy

例1

在 Rust 中,基本类型(如 i32f64bool 等) 实现了 Copy trait,这意味着它们在赋值或传递时会被复制,而不是移动所有权。因此,当你将 ab 传递给 sum 函数时,它们的值会被复制,而原始变量 ab 的所有权不会发生变化。

代码分析

fn sum(a: i32, b: i32) -> i32 {
    a + b
}

fn main() {
    let a = 3; // a 是一个 i32 类型,实现了 Copy trait
    let b = 4; // b 是一个 i32 类型,实现了 Copy trait
    let c = sum(a, b); // a 和 b 的值被复制,传递给 sum 函数
    println!("{}", c); // 输出 7
    println!("{}", a); // a 的所有权没有移动,仍然可以访问
}

关键点

  1. Copy trait

    • i32 是基本类型,实现了 Copy trait。
    • 当一个类型实现了 Copy trait 时,它的值在赋值或传递时会自动复制,而不是移动所有权。
  2. 所有权规则

    • 对于实现了 Copy 的类型,传递值给函数时不会发生所有权转移。
    • 对于未实现 Copy 的类型(如 StringVec 等),传递值给函数时会移动所有权,原始变量将无法再使用。
  3. 为什么可以输出 a

    • 因为 ai32 类型,传递时是复制值,而不是移动所有权,所以 a 仍然有效。

对比:未实现 Copy 的类型

如果你使用一个未实现 Copy 的类型(例如 String),情况会不同:

fn take_ownership(s: String) {
    println!("{}", s);
}

fn main() {
    let s = String::from("hello");
    take_ownership(s); // s 的所有权被移动到函数中
    println!("{}", s); // 这里会报错,因为 s 的所有权已经移动
}

总结

  • 对于实现了 Copy 的类型(如 i32),传递值时是复制,所有权不会移动。
  • 对于未实现 Copy 的类型(如 String),传递值时是移动所有权,原始变量将失效。

在你的代码中,abi32 类型,因此它们的值被复制,所有权没有移动,所以最后仍然可以输出 a

例2

在 Rust 中,&引用符号,用于创建一个值的引用(borrow),而不是直接传递值的所有权。具体到你的代码:

println!("{}, {}, {}", date, &params.campus, &params.position);

& 的作用

  1. 创建引用

    • &params.campus&params.position 是对 params.campusparams.position 的引用。
    • 引用允许你访问值,而不需要获取值的所有权。
  2. 避免所有权转移

    • 如果 params.campusparams.position 是未实现 Copy 的类型(例如 String),直接传递它们会导致所有权转移。
    • 使用 & 可以避免所有权转移,保留原始变量的所有权。
  3. 提高性能

    • 引用是轻量级的,只传递指针(内存地址),而不是复制整个值。
    • 对于较大的数据结构(如 StringVec),使用引用可以避免不必要的内存复制。

如果不加 & 会怎样?

如果不加 &,代码会尝试直接传递 params.campusparams.position 的所有权。具体行为取决于它们的类型:

情况 1:类型实现了 Copy trait

如果 params.campusparams.position 是实现了 Copy 的类型(例如 i32bool 等),不加 & 不会有问题,因为它们的值会被复制,而不是移动所有权。

let campus: i32 = 42;
let position: i32 = 24;
println!("{}, {}", campus, position); // 没问题,因为 i32 实现了 Copy

情况 2:类型未实现 Copy trait

如果 params.campusparams.position 是未实现 Copy 的类型(例如 String),不加 & 会导致所有权转移,后续代码将无法再使用这些变量。

let campus = String::from("Main Campus");
let position = String::from("Building A");
println!("{}, {}", campus, position); // 这里没问题
println!("{}", campus); // 这里会报错,因为 campus 的所有权已经转移到 println!

错误示例

let campus = String::from("Main Campus");
let position = String::from("Building A");
println!("{}, {}", campus, position); // 所有权转移
println!("{}", campus); // 报错:value borrowed here after move

总结

  • &:创建引用,避免所有权转移,适用于未实现 Copy 的类型(如 String)。
  • 不加 &
    • 对于实现了 Copy 的类型(如 i32),不会有问题。
    • 对于未实现 Copy 的类型(如 String),会导致所有权转移,后续代码无法再使用这些变量。

在你的代码中,如果 params.campusparams.positionString 类型,建议使用 & 来避免所有权转移。如果它们是基本类型(如 i32),可以不加 &,但加上也不会出错。

posted @ 2025-03-09 21:44  saulstavo  阅读(33)  评论(0)    收藏  举报