|
|
|
@ -122,7 +122,7 @@
|
|
|
|
|
|
|
|
|
|
### trait 对象执行动态分发
|
|
|
|
|
|
|
|
|
|
回忆一下第十章 [“泛型代码的性能”][performance-of-code-using-generics] 部分讨论过的,当对泛型使用 trait bound 时编译器所进行单态化处理:编译器为每一个被泛型类型参数代替的具体类型生成了非泛型的函数和方法实现。单态化所产生的代码进行 **静态分发**(*static dispatch*)。静态分发发生于编译器在编译时就知晓调用了什么方法的时候。这与 **动态分发** (*dynamic dispatch*)相对,这时编译器在编译时无法知晓调用了什么方法。在动态分发的情况下,编译器会生成在运行时确定调用了什么方法的代码。
|
|
|
|
|
回忆一下第十章 [“泛型代码的性能”][performance-of-code-using-generics] 部分讨论过的,当对泛型使用 trait bound 时编译器所执行的单态化处理:编译器为每一个被泛型类型参数代替的具体类型生成了函数和方法的非泛型实现。单态化产生的代码在执行 **静态分发**(*static dispatch*)。静态分发发生于编译器在编译时就知晓调用了什么方法的时候。这与 **动态分发** (*dynamic dispatch*)相对,这时编译器在编译时无法知晓调用了什么方法。在动态分发的场景下,编译器生成的代码到运行时才能确定调用了什么方法。
|
|
|
|
|
|
|
|
|
|
当使用 trait 对象时,Rust 必须使用动态分发。编译器无法知晓所有可能用于 trait 对象代码的类型,所以它也不知道应该调用哪个类型的哪个方法实现。为此,Rust 在运行时使用 trait 对象中的指针来知晓需要调用哪个方法。动态分发也阻止编译器有选择的内联方法代码,这会相应的禁用一些优化。尽管在编写示例 17-5 和可以支持示例 17-9 中的代码的过程中确实获得了额外的灵活性,但仍然需要权衡取舍。
|
|
|
|
|
|
|
|
|
@ -178,4 +178,4 @@ error: could not compile `gui` due to previous error
|
|
|
|
|
ch10-01-syntax.html#泛型代码的性能
|
|
|
|
|
[dynamically-sized]: ch19-04-advanced-types.html#动态大小类型和-sized-trait
|
|
|
|
|
[Rust RFC 255 ref]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
|
|
|
|
|
[Rust Reference ref]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
|
|
|
|
|
[Rust Reference ref]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
|
|
|
|
|