- 值传递(Pass by Value)
- 所有权特点:当使用值传递时,函数获取参数的所有权。这意味着一旦函数调用结束,参数所占用的内存会在函数作用域结束时被释放。
- 生命周期特点:参数的生命周期在函数结束时终止。
- 示例:
struct Point {
x: i32,
y: i32,
}
fn take_ownership(p: Point) {
println!("Taken ownership of Point: ({}, {})", p.x, p.y);
}
fn main() {
let my_point = Point { x: 10, y: 20 };
take_ownership(my_point);
// 这里不能再使用my_point,因为所有权已转移给take_ownership函数
// println!("{:?}", my_point); // 这行代码会报错
}
- 对结构体实例的影响:结构体实例的所有权被转移到函数中,原变量在函数调用后不再有效。
- 引用传递(Pass by Reference)
- 所有权特点:函数不获取参数的所有权,而是借用参数。借用有两种类型:不可变借用(
&T
)和可变借用(&mut T
)。
- 生命周期特点:借用的生命周期必须满足生命周期规则,即借用的生命周期不能长于被借用对象的生命周期。
- 不可变引用示例:
struct Point {
x: i32,
y: i32,
}
fn print_point(p: &Point) {
println!("Point: ({}, {})", p.x, p.y);
}
fn main() {
let my_point = Point { x: 10, y: 20 };
print_point(&my_point);
// 仍然可以使用my_point,因为所有权未转移
println!("{:?}", my_point);
}
struct Point {
x: i32,
y: i32,
}
fn modify_point(p: &mut Point) {
p.x += 1;
p.y += 1;
}
fn main() {
let mut my_point = Point { x: 10, y: 20 };
modify_point(&mut my_point);
println!("{:?}", my_point);
}
- 对结构体实例的影响:不可变引用允许函数读取结构体实例的内容,但不能修改。可变引用允许函数修改结构体实例的内容,而不会转移所有权,原变量在函数调用后仍然有效。
- 移动语义(Move Semantics)类似值传递但强调所有权转移本质
- 所有权特点:同值传递,所有权从调用者转移到被调用函数。这在Rust中是默认行为,尤其在涉及堆分配数据时。例如,
String
类型的数据。
- 生命周期特点:参数的生命周期在函数结束时终止。
- 示例:
fn print_string(s: String) {
println!("String: {}", s);
}
fn main() {
let my_string = String::from("Hello");
print_string(my_string);
// 这里不能再使用my_string,因为所有权已转移
// println!("{}", my_string); // 这行代码会报错
}
- 对结构体实例的影响:如果结构体中包含像
String
这样具有移动语义的成员,当结构体实例通过值传递(移动)给函数时,其内部成员的所有权也会转移,原结构体实例在函数调用后不再有效。