如何使用rust中的弱引用向量
我想在某个事件发生后保留要回调的对象数组。我不需要拥有这些对象,如果对象被解除分配,我可以从容器中惰性地删除侦听器 在概念上类似于这样,但会出现大量编译/所有权错误:如何使用rust中的弱引用向量,rust,weak-references,boxing,Rust,Weak References,Boxing,我想在某个事件发生后保留要回调的对象数组。我不需要拥有这些对象,如果对象被解除分配,我可以从容器中惰性地删除侦听器 在概念上类似于这样,但会出现大量编译/所有权错误: trait EventListener { fn event_occured(&mut self, event_name: String); } struct Listener { listeners : Vec<Weak<EventListener>> } impl Listener
trait EventListener {
fn event_occured(&mut self, event_name: String);
}
struct Listener {
listeners : Vec<Weak<EventListener>>
}
impl Listener {
fn observe_event(&mut self, listener: impl EventListener) {
self.listeners.push(Weak(listener)); // how can i box the listener in a weak container
}
fn listen_for_events() {
... did something here and figured it should broadcast to all listeners ...
for listener in self.listeners {
if listener.is_alive { listener.event_occured(event)} ; // how to check the weak ref is valid?
}
}
}
trait事件监听器{
发生fn事件(&mut self,事件名称:字符串);
}
结构侦听器{
听众:Vec
}
impl侦听器{
fn观察事件(&mut self,侦听器:impl EventListener){
self.listeners.push(弱(侦听器));//如何将侦听器装箱到弱容器中
}
fn侦听事件(){
…在这里做了一些事情,并认为它应该向所有听众广播。。。
对于self.listeners中的侦听器{
if listener.is_alive{listener.event_occurrend(event)};//如何检查弱引用是否有效?
}
}
}
所有者需要与此代码协作,以允许其保存弱引用。这意味着Listener::observe_event
需要采取弱
或Rc
。(或Arc
等效项)此时正在获取EventListener
值,当Listener::observe_event
返回时,该值当然会被释放。以下是一个基于您发布的代码的功能示例(在上):
似乎您对何时可以使用
弱有些困惑。当任何东西都被解除分配时,这不是一种机制。它仅在与Rc
配对时才起作用。我是否可以将其装箱到具有弱引用的强对象中?如果是这样,怎么做?i、 e.struct WeakBox{thing:weak}
并将向量更改为:listeners:Vec
@avnerbar,这不会有帮助,要使用weak
您需要在某个实际拥有EventListener
的地方有一个Rc
,所以不可能有这个问题?不确定它是否解决了,原因有两个1。回调应该是&mutself(我会解决这个问题,可能忘记了它)2。我希望清单是对现有对象的选择,并且不能将整个代码库重构到它们被实例化的每个地方,这样就不能对它们进行弱引用。Rust不是Python,默认情况下不是垃圾收集。如果没有引用计数(或等效值),就不能有弱引用。我更改了回调的可变性,因为Rc
s不能安全地提供对其内容的可变引用,如果需要的话,您需要将其包装成RefCell
或互斥体。
use std::rc::{Rc, Weak};
trait EventListener {
fn event_occured(&self, event_name: &String);
}
struct Listener {
listeners : Vec<Weak<dyn EventListener>>
}
impl Listener {
fn observe_event(&mut self, listener: &Rc<dyn EventListener>) {
self.listeners.push(Rc::downgrade(listener));
}
fn listen_for_events(&self) {
let event = String::new();
for listener in &self.listeners {
if let Some(strong_listener) = listener.upgrade() {
strong_listener.event_occured(&event);
}
}
}
}
struct A {}
impl EventListener for A {
fn event_occured(&self, _event_name: &String) {
println!("A");
}
}
struct B {}
impl EventListener for B {
fn event_occured(&self, _event_name: &String) {
println!("B");
}
}
fn main() {
let a: Rc<dyn EventListener> = Rc::new(A{});
let b: Rc<dyn EventListener> = Rc::new(B{});
let mut listener = Listener { listeners: vec![] };
listener.observe_event(&a);
listener.observe_event(&b);
listener.listen_for_events();
// B goes out of scope
drop(b);
listener.listen_for_events();
}
A
B
A