gpt4 book ai didi

将 Rc 转换为 Rc

转载 作者:行者123 更新时间:2023-11-29 08:01:34 28 4
gpt4 key购买 nike

Horse是一个实现 Animal 的结构特征。我有一个 Rc<Horse>和一个需要接收 Rc<Animal> 的函数, 所以我想从 Rc<Horse> 转换至 Rc<Animal> .

我这样做了:

use std::rc::Rc;

struct Horse;

trait Animal {}

impl Animal for Horse {}

fn main() {
let horse = Rc::new(Horse);
let animal = unsafe {
// Consume the Rc<Horse>
let ptr = Rc::into_raw(horse);
// Now it's an Rc<Animal> pointing to the same data!
Rc::<Animal>::from_raw(ptr)
};
}

这是一个好的解决方案吗?是否正确?

最佳答案

answer by Boiethios已经解释了可以使用 as 显式执行向上转换,甚至在某些情况下隐含地发生。我想补充一些有关机制的更多细节。

我将首先解释为什么您的不安全代码可以正常工作。

let animal = unsafe {
let ptr = Rc::into_raw(horse);
Rc::<Animal>::from_raw(ptr)
};

unsafe 中的第一行 block 消耗 horse并返回 *const Horse ,这是一个指向具体类型的指针。指针正是您所期望的——horse 的内存地址。的数据(忽略在您的示例中 Horse 是零大小且没有数据的事实)。在第二行,我们调用Rc::from_raw() ;让我们看一下该函数的原型(prototype):

pub unsafe fn from_raw(ptr: *const T) -> Rc<T>

因为我们正在为 Rc::<Animal> 调用此函数,预期的参数类型是 *const Animal .然而 ptr我们有类型 *const Horse ,那么为什么编译器会接受代码呢?答案是编译器执行了一个unsized coercion,这是一种隐式类型转换,即performed in certain places for certain types。 .具体来说,我们将指向具体类型的指针转​​换为指向实现 Animal任何类型的指针。特征。由于我们不知道确切的类型,现在指针不再是单纯的内存地址——它是内存地址和对象实际类型的标识符,即所谓的胖指针。这样,Rc从胖指针创建可以保留底层具体类型的信息,并且可以为Horse调用正确的方法。 Animal 的实现(如果有的话;在你的例子中 Animal 没有任何功能,但当然如果有的话它应该继续工作)。

我们可以通过打印它们的大小来看出两种指针之间的区别

let ptr = Rc::into_raw(horse);
println!("{}", std::mem::size_of_val(&ptr));
let ptr: *const Animal = ptr;
println!("{}", std::mem::size_of_val(&ptr));

这段代码首先生成ptr一个*const Horse , 打印指针的大小,然后使用未指定大小的强制转换 ptr*const Animal并再次打印它的大小。在 64 位系统上,这将打印

8
16

第一个只是一个简单的内存地址,而第二个是内存地址和指针对象的具体类型信息。 (具体来说,胖指针包含指向 virtual method table 的指针。)

现在让我们看看 Boethios 的回答中的代码发生了什么

let animal = horse as Rc<Animal>;

或等效

let animal: Rc<Animal> = horse;

还执行未定大小的强制转换。编译器如何知道如何为 Rc 执行此操作而不是原始指针?答案是 the trait CoerceUnsized exists specifically for this purpose .您可以阅读 RFC on coercions for dynamically sized types了解更多详情。

关于将 Rc<ConcreteType> 转换为 Rc<Trait>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53276642/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com