vector - 如何返回对添加到特征对象向量的具体类型的引用?

标签 vector rust

在这段代码中,我获取一个向量,创建一个结构实例,并将它添加到装箱的向量中:

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,这让我觉得这不是正确的方法。这个丑陋的 hack 是唯一的方法吗?

此外,虽然它在 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 ),所以 ptrb 的 Actor 阵容中幸存下来进入Box<dyn T> .

关于vector - 如何返回对添加到特征对象向量的具体类型的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55784587/

相关文章:

c++ - std::vector 在 push_back 期间多次调用析构函数?

r - 如何向量化从列索引向量扩展压缩稀疏矩阵?

generics - 通用函数接受 &str 或移动字符串而不复制

ruby - 通过 FFI 从 rust 到 ruby ,弦变空

rust - 生命周期注释,或 &str vs String

c++ - 在高级类的 vector 中调用派生类的方法

c++ - 如何将文件读入元组 vector ?

rust - 为什么不能在结构定义中省略生命周期?

c++ - std::vector 迭代器作为类成员

rust - 如何将向量解析为函数?