零成本抽象 是Rust的一个关键理念,意味着抽象(例如,泛型类型、迭代器、traits)不应该比手动编写类似代码带来额外的时间或内存开销。也就是说,高级代码经过优化后编译成的效率应与低级代码相同。
Rust通过单态化机制实现这一点:泛型代码为每个具体类型单独编译,没有动态调用。基于traits/泛型编写的迭代器和闭包在优化后被编译器展开为直接的强类型代码,消除了多余的封装。
零成本迭代器示例:
let v = vec![1,2,3]; let sum: i32 = v.iter().map(|x| x * 2).sum();
此代码片段在优化后几乎被编译器转换为手动循环:
let mut sum = 0; for x in &v { sum += x * 2; }
在Rust中,零成本抽象是否意味着在使用trait对象(例如,&dyn Trait)时不会有运行时开销?
回答:不! 由于通过vtable动态选择方法时会产生运行时开销——当使用dyn Trait而不是泛型函数时。零成本仅在静态(单态化的)泛型抽象中获得。
示例:
trait Speaker { fn speak(&self); } fn say_twice<T: Speaker>(v: T) { v.speak(); v.speak(); } fn say_twice_dyn(v: &dyn Speaker) { v.speak(); v.speak(); } // 第一个调用被单态化,第二个通过vtable
故事
故事
故事
在一个外部库中创建了一个泛型结构,并作为Box<dyn Trait>返回。尽管实现是泛型的,但由于在运行时引入了抽象,失去了零成本。