面试题答案
一键面试对于 &str
参数
- 所有权:
- 调用函数时传递的
&str
类型参数不转移所有权。&str
是字符串切片,它指向某个字符串数据,该数据的所有权仍归原始所有者。例如:
fn print_name(name: &str) { println!("Name: {}", name); } fn main() { let s = String::from("Alice"); print_name(&s); // 这里 s 的所有权未改变,仍可继续使用 s println!("After function call: {}", s); }
- 调用函数时传递的
- 借用规则:
- 必须遵循Rust的借用规则。在同一作用域内,不能同时存在可变借用和不可变借用。例如:
fn main() { let mut s = String::from("Bob"); let r1 = &s; // 下面这行代码会报错,因为 r1 是不可变借用,在 r1 有效的作用域内不能有可变借用 // let r2 = &mut s; print_name(r1); }
- 借用的生命周期必须足够长,要长于函数调用期间对借用的使用。例如:
fn main() { let name; { let s = String::from("Charlie"); name = &s; } // 这里会报错,因为 s 的生命周期在花括号结束时就结束了,而 name 试图在 s 生命周期结束后使用它 // print_name(name); }
对于自定义结构体引用参数
- 额外所有权考虑:与
&str
类似,传递自定义结构体的引用时,结构体的所有权不转移。例如:struct Person { name: String, age: u8 } fn print_person(p: &Person) { println!("Name: {}, Age: {}", p.name, p.age); } fn main() { let p = Person { name: String::from("David"), age: 30 }; print_person(&p); // p 的所有权未改变,可继续使用 p }
- 额外借用规则:
- 如果结构体中有可变字段,在借用结构体时要注意借用规则。例如:
struct Counter { value: u32 } fn increment(c: &mut Counter) { c.value += 1; } fn main() { let mut counter = Counter { value: 0 }; increment(&mut counter); // 同一时间只能有一个可变借用,在可变借用期间不能有不可变借用 // let r = &counter; // 这行会报错 }
- 如果结构体包含其他具有复杂生命周期的类型(如引用类型),要确保所有相关的生命周期都能正确匹配。例如:
这里struct Data<'a> { ref_value: &'a i32 } fn print_data(d: &Data<'_>) { println!("Value: {}", d.ref_value); } fn main() { let num = 42; let data = Data { ref_value: &num }; print_data(&data); }
Data
结构体中的ref_value
引用的生命周期必须与传递给print_data
函数的Data
结构体引用的生命周期相匹配。