面试题答案
一键面试- 引用与所有权的配合:
- 不可变引用:
- 在Rust中,所有权规则确保同一时刻只能有一个所有者。不可变引用允许我们在不获取所有权的情况下访问数据,并且可以有多个不可变引用同时存在。这有助于在需要读取数据时避免数据竞争。例如:
- 不可变引用:
fn main() {
let s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
}
- 在这段代码中,`s`拥有字符串的所有权,`r1`和`r2`是对`s`的不可变引用。多个不可变引用可以同时存在,因为它们只读取数据,不会修改数据,所以不会产生数据竞争。
- 可变引用:
- 可变引用允许我们修改数据,但为了避免数据竞争,同一时刻只能有一个可变引用存在,并且在有可变引用时不能有不可变引用。例如:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
r1.push_str(", world");
println!("{}", r1);
}
- 这里`mut s`表明`s`是可变的,`r1`是对`s`的可变引用。通过`r1`可以修改`s`所指向的字符串。如果试图在有可变引用`r1`的同时创建不可变引用,会导致编译错误。
2. 违反引用规则的编译错误及修改:
- 错误示例1:同时存在可变和不可变引用:
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &mut s;
println!("{} and {}", r1, r2);
}
- 编译时会报错,类似`error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable`。原因是同时存在对`s`的不可变引用`r1`和可变引用`r2`,违反了Rust的引用规则。
- **修改方法**:确保在创建可变引用之前,不可变引用不再使用。例如:
fn main() {
let mut s = String::from("hello");
let r1 = &s;
println!("{}", r1);
let r2 = &mut s;
r2.push_str(", world");
println!("{}", r2);
}
- 错误示例2:多个可变引用:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
r1.push_str(", world");
r2.push_str("!");
}
- 编译时会报错,类似`error[E0499]: cannot borrow `s` as mutable more than once at a time`。因为同一时刻有多个可变引用`r1`和`r2`指向`s`。
- **修改方法**:确保同一时刻只有一个可变引用。例如:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
r1.push_str(", world");
let r2 = &mut s;
r2.push_str("!");
}
这样修改后,r1
使用完后再创建r2
,就不会违反引用规则。