Rust、std::cell::Cell - 获取对内部数据的不可变引用

Jak*_*dło 3 variables pointers unsafe reference rust

浏览 std::cell::Cell 的文档,我没有看到如何检索对内部数据的非可变引用。只有get_mut方法:https://doc.rust-lang.org/std/cell/struct.Cell.html#method.get_mut

我不想使用这个函数,因为我想&self&self mut.

我找到了采用原始指针的替代解决方案:

use std::cell::Cell;

struct DbObject {
    key: Cell<String>,
    data: String
}

impl DbObject {
    pub fn new(data: String) -> Self {
        Self {
            key: Cell::new("some_uuid".into()),
            data,
        }
    }

    pub fn assert_key(&self) -> &str {
        // setup key in the future if is empty...
        let key = self.key.as_ptr();
        unsafe {
            let inner = key.as_ref().unwrap();
            return inner;
        }
    }
}

fn main() {
    let obj = DbObject::new("some data...".into());
    let key = obj.assert_key();
    println!("Key: {}", key);
}
Run Code Online (Sandbox Code Playgroud)

有没有什么方法可以在不使用 unsafe 的情况下做到这一点?如果没有,也许 RefCell 在这里会更实用?

谢谢你的帮助!

mca*_*ton 9

首先,如果你有一个&mut T,你可以轻松地&T从中得到一个 。所以你可以使用get_mutget &T

但是要从 a 获取&mut Ta,Cell<T>您需要该单元格是可变的,因为get_mut需要一个&mut self参数。根据设计,这是获取对单元格内部对象的引用的唯一方法。

通过要求使用方法&mut self从单元格中获取引用,您可以在编译时使用借用检查器检查独占访问。请记住,单元格具有内部可变性,并且有一个方法set(&self, val: T),即可以修改非绑定值的方法mut!如果有一个get(&self) -> &T方法,借用检查器无法确保您在设置对象时不持有对内部对象的引用,这将是不安全的。


TL;DR:按照设计,你无法从&Tmut Cell<T>. 使用get_mut(需要mut细胞)或set/ replace(对非细胞起作用mut)。如果这是不可接受的,那么请考虑使用RefCell,它可以&T以一定的运行时成本让您脱离非 mut 实例。