3.3 拥有型 Trait 对象
03-拥有型 Trait 对象 — Comprehensive Rust
2 分钟阅读
译文 · 基于 Comprehensive Rust
原文链接: https://google.github.io/comprehensive-rust/smart-pointers/trait-objects.html
3.3 拥有型 Trait 对象
我们之前见过 trait 对象如何与引用一起使用,例如 &dyn Pet。也可以把 trait 对象与 Box 等智能指针结合,创建拥有型 trait 对象:Box<dyn Pet>。
| |
分配 pets 之后的内存布局:
Stack Heap
.- - - - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.
: : : :
: "pets: Vec<Box<dyn Pet>>" : : "data: Cat" +----+----+----+----+ :
: +-----------+-------+ : : +-------+-------+ | F | i | d | o | :
: | ptr | o---+-------+--. : | lives | 9 | +----+----+----+----+ :
: | len | 2 | : | : +-------+-------+ ^ :
: | capacity | 2 | : | : ^ | :
: +-----------+-------+ : | : | '-------. :
: : | : | data:"Dog"| :
: : | : | +-------+--|-------+ :
`- - - - - - - - - - - - - - - -' | : +---|-+-----+ | name | o, 4, 4 | :
`--+-->| o o | o o-|----->| age | 5 | :
: +-|---+-|---+ +-------+----------+ :
: | | :
`- - -| - - |- - - - - - - - - - - - - - - - -'
| |
| | "Program text"
.- - -| - - |- - - - - - - - - - - - - - - - -.
: | | vtable :
: | | +----------------------+ :
: | `----->| "<Dog as Pet>::talk" | :
: | +----------------------+ :
: | vtable :
: | +----------------------+ :
: '----------->| "<Cat as Pet>::talk" | :
: +----------------------+ :
: :
'- - - - - - - - - - - - - - - - - - - - - - -'
- 实现同一 trait 的类型可能大小不同。这使得上面例子中不可能有
Vec<dyn Pet>这类东西。dyn Pet是告诉编译器:这是一个实现了Pet的动态大小类型。- 在本例中,
pets分配在栈上,向量数据在堆上。两个向量元素都是_胖指针_:
- 胖指针是双倍宽度的指针。它有两个组成部分:指向实际对象的指针,以及指向该对象特定
Pet实现的虚方法表(vtable)的指针。- 名为 Fido 的
Dog的数据是name与age字段。Cat有一个lives字段。- 比较上面例子中的这些输出:
1 2 3 4 5 6 7// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 # println!("{} {}", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>()); println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); println!("{}", std::mem::size_of::<&dyn Pet>()); println!("{}", std::mem::size_of::<Box<dyn Pet>>());