vector - 如何返回对添加到特征对象向量中的具体类型的引用?
问题描述
在这段代码中,我获取一个向量,创建一个结构实例,并将其添加到装箱的向量中:
trait T {}
struct X {}
impl T for X {}
fn add_inst(vec: &mut Vec<Box<T>>) -> &X {
let x = X {};
vec.push(Box::new(x));
// Ugly, unsafe hack I made
unsafe { std::mem::transmute(&**vec.last().unwrap()) }
}
显然,它使用mem::transmute
,这让我觉得这不是正确的方法。这个丑陋的黑客是唯一的方法吗?
此外,虽然它在 Rust 1.32 中编译,但在 Rust 1.34 中失败:
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> src/lib.rs:10:14
|
10 | unsafe { std::mem::transmute(&**vec.last().unwrap()) }
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `&dyn T` (128 bits)
= note: target type: `&X` (64 bits)
解决方案
我认为这段代码是安全的:
fn add_inst(vec: &mut Vec<Box<dyn T>>) -> &X {
let x = X {};
let b = Box::new(x);
let ptr = &*b as *const X;
vec.push(b);
unsafe { &*ptr }
}
诀窍是在将原始指针*const X
转换为Box<dyn T>
. 然后,您可以在从函数返回之前将其转换回引用。这是安全的,因为一个装箱的值永远不会移动,(当然,除非它移出Box
),所以在into的转换中ptr
幸存下来。b
Box<dyn T>
推荐阅读
- java - Android:通过 android 数据绑定将 lambda 传递给回收器适配器
- java - 如何提取和替换具有特定格式的字符串?
- java - 具有 Microsoft EWS 给定 TimeZone 的 ExchangeService 实例或 GetUserAvailabilityResults
- excel - excel检查用户输入是否在范围内
- c++ - 使用 RecordSet 读取 nText
- jquery - ASP.NET Core jQuery .ajax 帖子总是为空?
- reactjs - 状态未从子回调中更新
- r - R中有序probit / logit模型中每个变量的单一边际效应
- sql - 外部连接中的位置 vs ON
- asp.net-mvc - Windows 10 更新后从 cordova (android/ios webview) 或 Chrome > 80 访问站点时会话状态不保持