use std::ops::Deref;

struct Test {
    last: &'static str,
    list: Vec<String>,
}

// This is safe because we own the value and will not modify it.
// When dropping, `last` will be dropped without freeing the memory.
impl Test {
    pub fn new(value: String) -> Self {
        Self {
            last: unsafe { std::mem::transmute(value.deref()) },
            list: vec![value],
        }
    }
    pub fn insert(&mut self, value: String) {
        self.last = unsafe { std::mem::transmute(value.deref()) };
        self.list.push(value);
    }
    pub fn last(&self) -> &str {
        self.last
    }
}

有没有可能用泛型做类似的构造,比如Test<T:Deref>? 我不确定deref()是否保证了任何"永久"堆地址(在我的实现的有限上下文中),或者它保证了吗?

上面的代码似乎是安全的,因为在String上调用deref()会给出一个指向堆的宽指针,并且该地址永远不会改变,除非字符串本身被更改或者所有权被返还给调用者.

请注意,我需要为我的用例存储&str,而不是使用ManuallyDrop::new(unsafe { ptr::read(&value) })创建的ManuallyDrop<String>.

推荐答案

正如你所怀疑的,这并不安全.

存在提供StableDeref特性的stable_deref_trait,而StableDeref特性应该用于这样的用例.然而,this crate is known to be unsound(或至少以不可靠的方式使用),因为例如,它实现了Box but it is not clear whether it is okay to move a Box while there are references to itStableDeref(在堆叠borrow 下,这是UB,并且MIRI会将其标记为UB).

如果您想要*mut T%安全,堆分配所有存储的对象并将它们存储为*mut T(出于上面提到的原因,not,Box<T>),那么您可以将对它们的引用存储在相同的 struct 中.

Rust相关问答推荐

即使参数和结果具有相同类型,fn的TypId也会不同

如何定义实现同名但返回类型不同的 struct 的函数

在本例中,为什么我不能一次多次borrow 可变变量?

在Rust中,Box:ed struct 与普通 struct 在删除顺序上有区别吗?

在复制类型中使用std::ptr::WRITE_VILAR进行内部可变性的安全性(即没有UnSafeCell)

在 Rust 中,在需要引用 self 的 struct 体方法中使用闭包作为 while 循环条件

如何对一个特征的两个实现进行单元测试?

为什么某些类型参数仅在特征边界中使用的代码在没有 PhantomData 的情况下进行编译?

Rust 1.70 中未找到 Trait 实现

方法可以被误认为是标准特性方法

有什么方法可以通过使用生命周期来减轻嵌套生成器中的当生成器产生时borrow 可能仍在使用错误?

在 Rust 中,Weak 如何知道内部值何时被删除?

如何将 Rust 字符串转换为 i8(c_char) 数组?

第 7.4 章片段中如何定义 `thread_rng`

发生移动是因为 `data` 的类型为 `Vec`,它没有实现 `Copy` 特性

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

为什么我可以在没有生命周期问题的情况下内联调用 iter 和 collect?

如何将 u8 切片复制到 u32 切片中?

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?

守卫如何影响匹配语句?