当我将具体结构引用传递给采用特征对象的函数时会发生什么?

问题描述 投票:0回答:1

在下面的代码中,我有一个简单的特征 A 和一个实现 A 的结构 Foo...

接下来,我定义了一个函数,它引用了一个特征对象。我从 main() 传入对具体 Foo 的引用。这工作正常并成功调用了特征中的方法。

trait A {
    fn do_something(&self) {
        println!("Doing something.");
    }
}

struct Foo {}
impl A for Foo {}

fn main() {
    let foo = Foo {};
    make_do_something(&foo);
}

fn make_do_something(a: &dyn A) {
    a.do_something();
}

Rust 编译器在这里做什么?具体的 Foo 引用是否自动强制转换为 Trait 对象引用?也就是说,是否在引用我的具体对象的堆上创建了一个新的特征对象?我在文档中找不到关于它如何工作的清晰描述。

rust traits trait-objects
1个回答
0
投票

具体的 Foo 引用是否自动强制转换为 Trait 对象引用?

是的,

&Foo
强制
&dyn A
&Foo
包含一个指向
Foo
数据的指针(在您的示例中恰好是零字节长,但这没有区别);
&dyn A
由该指针 指向从 impl A for Foo 生成的 vtable
 的指针组成。

是在堆上创建的新特征对象

没有;特征对象需要额外的数据来引用它,而不是存储它。

将它与 Rust 中另一种主要的动态大小 (

!Sized
) 类型进行比较,切片:一个
&Foo
包含一个指向
Foo
的指针,而一个
&[Foo]
包含该指针 和一个长度 .它们可能指向相同的数据(你可以双向转换),但指针不同。

一般来说,指向一个

Sized
类型的值只需要指向数据的机器指针;指向
!Sized
类型的值需要额外的信息(称为“metadata”)。

每个指向动态大小类型的指针都是通过强制构造的,在这种情况下,编译器插入编译时已知的必要数据(特征对象的 vtable,或从指针数组强制转换的切片指针的长度) ,或者通过知道它正在为什么构造指针的库代码(例如,当

Vec<T>
产生
&[T]
时)。

© www.soinside.com 2019 - 2024. All rights reserved.