You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带生命周期参数的结构体结合Weak引用的使用问题

用Weak智能指针实现Rust观察者模式的生命周期问题

我想用Weak智能指针实现观察者模式,写了如下代码:

use std::cell::RefCell;
use std::rc::{Rc, Weak};

struct Observable {
    observers: Vec<Weak<Observer>>,
}

impl Observable {
    fn new() -> RefCell<Observable> {
        RefCell::new(Self {
            observers: Vec::new(),
        })
    }
}

struct Observer<'a> {
    parent: &'a RefCell<Observable>,
}


fn observe(observable: &RefCell<Observable>) -> Rc<Observer> {
    let observer = Observer {
        parent: observable,
    };
    let observer = Rc::new(observer);
    observable.borrow_mut().observers.push(Rc::downgrade(&observer));
    observer
}


fn main() {
    let mut observable = Observable::new();
    let observer = observe(&observable);
}

但这段代码编译失败,报错信息如下:

error[E0106]: missing lifetime specifier
 --> src/main.rs:5:25
  |
5 |     observers: Vec<Weak<Observer>>,
  |                         ^^^^^^^^ expected named lifetime parameter
  |
help: consider introducing a named lifetime parameter
  |
4 ~ struct Observable<'a> {
5 ~     observers: Vec<Weak<Observer<'a>>>,
  |

For more information about this error, try `rustc --explain E0106`.

请问能否在observers字段添加该生命周期参数,或是移除Observer的生命周期参数,同时避免循环生命周期依赖问题?是否有办法让Weak指针的特性同时作用于Observer自身的生命周期以及引用的生命周期?


解决方案

核心问题在于原代码中Observer持有Observable的引用,导致必须添加生命周期约束,而Observable又持有Observer的Weak指针,形成了循环的生命周期依赖,Rust编译器无法通过这种约束。正确的做法是让Observer持有Observable的Weak指针而非引用,彻底移除生命周期参数,同时利用Weak的特性避免循环引用和悬垂引用。

修改后的代码如下:

use std::cell::RefCell;
use std::rc::{Rc, Weak};

struct Observable {
    observers: Vec<Weak<Observer>>,
}

impl Observable {
    fn new() -> Rc<RefCell<Self>> {
        Rc::new(RefCell::new(Self {
            observers: Vec::new(),
        }))
    }

    // 示例:通知所有观察者的方法
    fn notify(&self) {
        println!("Observable发出通知");
    }
}

struct Observer {
    parent: Weak<RefCell<Observable>>,
}

impl Observer {
    fn new(parent: &Rc<RefCell<Observable>>) -> Rc<Self> {
        let observer = Rc::new(Self {
            parent: Rc::downgrade(parent),
        });
        parent.borrow_mut().observers.push(Rc::downgrade(&observer));
        observer
    }

    // 示例:观察者接收通知的方法
    fn update(&self) {
        match self.parent.upgrade() {
            Some(observable) => observable.borrow().notify(),
            None => println!("Observable已被销毁"),
        }
    }
}

fn main() {
    let observable = Observable::new();
    let observer = Observer::new(&observable);
    
    // 测试正常通知
    observer.update();
    
    // 销毁Observable,测试Weak指针的行为
    drop(observable);
    observer.update();
}

关键修改说明

  • 移除生命周期参数:将Observer中的&'a RefCell<Observable>替换为Weak<RefCell<Observable>>,不再需要生命周期约束,因为Weak指针本身不依赖对象的生命周期,而是通过upgrade()方法检查对象是否存活。
  • Observable用Rc包裹:只有被Rc管理的对象才能生成Weak指针,因此将Observable::new()的返回值改为Rc<RefCell<Observable>>。
  • 避免循环引用:Observable持有Observer的Weak指针,Observer持有Observable的Weak指针,两者都不增加对方的引用计数,因此不会形成循环引用导致内存泄漏。
  • 安全的对象访问:通过Weak::upgrade()可以安全地获取Observable的Rc(如果对象还存活),否则返回None,彻底避免悬垂引用问题。

内容的提问来源于stack exchange,提问作者frankplow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:55:24