#指针 #内部可变性 #内存 #单元 #工具

nightly 内部_可变性_指针

围绕 Rc<RefCell<T>> 的包装,允许直接访问内部方法

1 个不稳定版本

0.3.6 2022 年 7 月 9 日
0.3.5 2022 年 7 月 9 日
0.3.4 2022 年 1 月 8 日
0.3.3 2021 年 12 月 29 日
0.1.2 2021 年 11 月 26 日

#2153 in Rust 模式

47 次每月下载

MIT 许可证

47KB
1.5K SLoC

crates.io downloads docs.rs

安全性

由于这个库本质上绕过了使用 RefCell 提供的运行时安全性,因此 DerefMut 的实现是不安全的。请参阅 问题 #2
由于这个原因,Imp::new(..) 已被标记为 unsafe

内部可变性指针

围绕 Rc<RefCell<T>> 的包装,允许直接访问内部方法,无需使用 .borrow().borrow_mut(),从而提供更平滑的指针体验。

let mut k = Imp::new(String::new());
let p = k.clone(); // Clone the pointer.
k.push_str("yo");
println!("{} {}", k, p); // Prints "yo yo"

还允许使用运算符

let mut k = Imp::new(5);
let p = k.clone(); // Clone the pointer.
k += 5;
println!("{} {}", k, p); // Prints "10 10"

Rc<RefCell<T>> 的最大区别在于,如果您想使用 &mut self 方法,则您的指针实例需要标记为 mut,与可以调用 .borrow_mut()Rc<RefCell<T>> 实例相比,无需使用 mut 关键字。但这并不意味着所有指针的克隆都需要是可变的!

let k = Imp::new(String::new());
let mut p = k.clone(); // Clone the pointer.
p.push_str("yo");
println!("{:?} {:?}", k, p); // Prints "yo yo"

还支持所有 trait 对象的动态分派,在可变和不可变上下文中都支持!

trait Animal {
    fn sound(&self) -> &'static str;
    fn volume(&self) -> i32;
    fn set_volume(&mut self, v: i32);
}

#[derive(Clone, Copy)]
struct Sheep {
    volume: i32,
}
impl Animal for Sheep {
    fn sound(&self) -> &'static str {
        "baah"
    }

    fn volume(&self) -> i32 {
        self.volume
    }

    fn set_volume(&mut self, v: i32) {
        self.volume = v;
    }
}

#[derive(Clone, Copy)]
struct Dog {
    volume: i32,
}
impl Animal for Dog {
    fn sound(&self) -> &'static str {
        "bark"
    }

    fn volume(&self) -> i32 {
        self.volume
    }

    fn set_volume(&mut self, v: i32) {
        self.volume = v;
    }
}
let s = Sheep { volume: 10 };
let d = Dog { volume: 15 };

let mut rc_refcell: Vec<Rc<RefCell<dyn Animal>>> =
    vec![Rc::new(RefCell::new(s)), Rc::new(RefCell::new(d))];
let mut imp: Vec<Imp<dyn Animal>> = vec![Imp::new(s), Imp::new(d)];

rc_refcell.iter_mut().for_each(|a| {
    let v = a.borrow().volume();
    a.borrow_mut().set_volume(v * 2);
});

imp.iter_mut().for_each(|a| {
    let v = a.volume();
    a.set_volume(v * 2);
});

let rc_refcell = rc_refcell
    .iter()
    .map(|p| p.borrow().volume())
    .collect::<Vec<_>>();
let imp = imp.iter().map(|p| p.volume()).collect::<Vec<_>>();

println!("{:?}", rc_refcell); // Prints [20, 30]
println!("{:?}", imp);        // Prints [20, 30]

无运行时依赖

特性