面试题答案
一键面试struct MyStruct {
data: Box<Vec<i32>>
}
impl MyStruct {
fn get_first(&self) -> i32 {
// 这里首先通过 `&self` 获取 `MyStruct` 的不可变引用。
// `self.data` 是一个 `Box<Vec<i32>>`,要访问 `Vec<i32>` 内部的数据,需要进行解引用。
// 因为 `&self` 是不可变引用,所以 `self.data` 也是不可变的,这里的解引用操作是安全的。
// 首先解引用 `Box` 得到 `Vec<i32>` 的不可变引用,再通过 `get(0)` 方法获取 `Option<&i32>`。
// `get(0)` 方法返回 `Option` 类型是为了处理 `Vec` 为空的情况。
// 这里假设 `Vec` 一定有元素,使用 `unwrap` 来获取 `&i32`。
// 最后再次解引用 `&i32` 得到 `i32` 值。
*self.data.get(0).unwrap()
}
}
解引用操作与所有权规则协同工作
&self
引用:当调用get_first
方法时,&self
是MyStruct
的不可变引用。这意味着MyStruct
实例本身和其所有字段(包括data
)都不能被修改。Box
解引用:self.data
是Box<Vec<i32>>
类型,通过self.data
访问Box
内部的数据需要解引用。由于self
是不可变引用,self.data
也是不可变的,所以可以安全地解引用Box
以获取其内部Vec<i32>
的不可变引用。Vec
元素访问:通过解引用Box
得到Vec<i32>
的不可变引用后,调用get(0)
方法获取Vec
中第一个元素的不可变引用Option<&i32>
。如果Vec
为空,get(0)
返回None
,这里假设Vec
一定有元素,使用unwrap
方法获取&i32
。- 最终解引用:最后再次解引用
&i32
以返回实际的i32
值。
可能遇到的所有权相关错误及解决办法
Vec
为空:如果Vec
为空,get(0)
会返回None
,调用unwrap
会导致程序 panic。解决办法是在调用unwrap
之前进行检查,例如:
fn get_first(&self) -> Option<i32> {
self.data.get(0).map(|&x| x)
}
这样返回 Option<i32>
,调用者可以选择合适的方式处理 None
情况。
2. 所有权转移:如果在 get_first
方法中尝试将 self.data
的所有权转移出去,会违反所有权规则。例如,如果尝试 return self.data.remove(0);
,会报错,因为 self
是不可变引用,不能转移 self.data
的所有权。解决办法是使用不可变访问方法,如上述实现中使用 get
方法。