面试题答案
一键面试变量的可变性(mutability)
在Rust中,默认情况下变量是不可变的。这意味着一旦绑定了一个值,就不能再改变它。使用mut
关键字可以使变量可变,允许对其值进行修改。这有助于防止意外的变量修改,提高代码的稳定性和可维护性。
所有权(ownership)
所有权是Rust的核心特性,它通过一套规则来管理内存,无需垃圾回收器。每个值在Rust中都有一个所有者(变量),当所有者离开作用域时,值会被自动释放。所有权规则如下:
- 每个值都有一个所有者。
- 同一时刻,一个值只能有一个所有者。
- 当所有者离开作用域,这个值将被丢弃。
代码示例
fn main() {
// 定义一个不可变变量
let s1 = String::from("hello");
// 尝试修改s1会导致编译错误,因为s1不可变
// s1.push_str(", world");
// 定义一个可变变量
let mut s2 = String::from("goodbye");
s2.push_str(", cruel world");
// 所有权转移示例
let s3 = s2;
// 这里s2不再有效,因为所有权转移到了s3
// println!("{}", s2); // 这行代码会导致编译错误
// 函数调用中的所有权转移
takes_ownership(s3);
// 这里s3不再有效,因为所有权转移到了takes_ownership函数内部
// println!("{}", s3); // 这行代码会导致编译错误
let x = 5;
makes_copy(x);
// 这里x仍然有效,因为i32类型实现了Copy trait,不会发生所有权转移
println!("x is: {}", x);
}
fn takes_ownership(some_string: String) {
println!("{}", some_string);
}
fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
}
违反所有权规则的编译错误
- 双重释放错误:如果试图在所有权转移后继续使用原变量,编译器会报错。例如,在上述代码中,如果取消注释
println!("{}", s2);
,编译器会提示s2
在这一作用域中已被移动。 - 悬垂指针错误:Rust通过所有权系统避免了悬垂指针的问题。因为当变量离开作用域时,其值会被自动释放,不存在指针指向无效内存的情况。如果代码试图创建类似悬垂指针的情况,编译器会拒绝编译。