面试题答案
一键面试在Rust中,可以这样实现:
trait Animal {
fn speak(&self);
}
struct Dog;
struct Cat;
impl Animal for Dog {
fn speak(&self) {
println!("Woof!");
}
}
impl Animal for Cat {
fn speak(&self) {
println!("Meow!");
}
}
fn main() {
let animals: Vec<Box<dyn Animal>> = vec![
Box::new(Dog),
Box::new(Cat)
];
for animal in animals {
animal.speak();
}
}
生命周期标注的作用
&self
:在Animal
特征中的speak
方法使用&self
,这里的&
表示借用。&self
意味着该方法不会获取self
的所有权,而是借用self
。这种方式保证了对象在方法调用期间的有效性,同时也避免了方法调用结束后对象被意外释放。例如,Dog
和Cat
结构体在实现speak
方法时,使用&self
可以确保Dog
和Cat
实例在调用speak
方法时不会被移动或释放。Box<dyn Animal>
:在main
函数中,Box<dyn Animal>
是一个指向实现了Animal
特征的动态对象的智能指针。Box
负责管理其所包含对象的内存,当Box
离开作用域时,它会自动释放其所包含的对象。dyn
关键字用于表示动态分发,意味着具体的类型在运行时才能确定。在这个例子中,Box<dyn Animal>
存储了Dog
和Cat
实例,Box
的生命周期管理确保了Dog
和Cat
实例在animals
向量离开作用域时被正确释放,避免了内存泄漏。Vec<Box<dyn Animal>>
中的Box
使得向量可以拥有这些动态对象的所有权,并在向量被销毁时清理它们的内存,从而防止了悬垂指针和内存泄漏问题。