如何使用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