< 返回版块

sstudioer 发表于 2021-03-09 15:35

use std::cell::Cell;
use std::borrow::Borrow;
use std::rc::Rc;

struct A{
    src: Rc<B>,
}

struct B{
    src: Rc<A>,
}

fn main() {
    let a = Rc::new(A{});  // 这里要求初始化; 关键是不能初始化; 也初始化不了;
    let b=  Rc::new(B{}); 
    a.src = b;
    b.src = a;
}

我知道应该用Week; 这只是演示; 相互嵌套该如何实现? 这是最非常常用的功能

评论区

写评论
suozhaoyu0530 2021-03-10 11:12

可以使用智能指针Box

如果涉及到同一线程会多次调用,使用Rc包一层,多线程的使用Arc

如果还需要更改使用Mutex包一下

基本上长这个样:Rc 虽然看着很麻烦,但使用起来还是挺顺手的

在这种模式下,需要注意死锁的问题,因为Mutex使用时需要lock一下,这种情况下很容易出现两个相互等待对方解锁,这种情况编译器发现不了,但运行时会出现卡死的情况 解决方法也很简单,使用作用域就可以了

大体上可以写成这样:

fn test(a: Rc<Mutex<Box<A>>>) {
    // 第一种逻辑 
    { 
        let a = a.clone(); 
        let mut a = a.lock().unwrap(); 
        //TODO 逻辑 
    } 
    // 第二种逻辑 
    { 
        let a = a.clone();
        let mut a = a.lock().unwrap();
        //TODO 逻辑 
    } 
}
w 2021-03-10 09:27

像楼上说的,这种嵌套可以用weak。


struct A {
    src: RefCell<Weak<B>>,
}

struct B {
    src: RefCell<Weak<A>>,
}

fn main() {

    let a = Rc::new(A { src: RefCell::new(Default::default()) });

    let b = Rc::new(B { src: RefCell::new(Default::default()) });

    *a.src.borrow_mut() = Rc::downgrade(&b);
    *b.src.borrow_mut() = Rc::downgrade(&a);

}

方不方便见仁见智,相比java这种写起来的确会麻烦一些。

Mike Tang 2021-03-09 22:26

还是个思维的转变过程,这个去适应后会发现自己的架构能力竟然还能再上台阶。rustc是个一等一的老师。

作者 sstudioer 2021-03-09 19:58

关键是总用? 或者判断, 或者存入变量也不是个事啊; 写游戏服务器, 存在大量嵌套, 若如此写法实在是太复杂了;

👇
Mike Tang: 说明本来就该判断。Rust给你指出来了潜在的风险,这些风险也许你之前根本没意识到。

Mike Tang 2021-03-09 18:23

说明本来就该判断。Rust给你指出来了潜在的风险,这些风险也许你之前根本没意识到。

--
👇
sstudioer: thanks; 返回的是Option<Rc>, 还要判断None;

--
👇
Mike Tang: 就是weak呀,读一下weak的文档就能用了。

作者 sstudioer 2021-03-09 17:56

thanks; 返回的是Option<Rc>, 还要判断None;

--
👇
Mike Tang: 就是weak呀,读一下weak的文档就能用了。

Ryan-Git 2021-03-09 17:51

c++ 里循环依赖如果用智能指针不也得 weak ptr。。一回事 裸指针自己管就是 unsafe 么

Mike Tang 2021-03-09 17:29

就是weak呀,读一下weak的文档就能用了。

作者 sstudioer 2021-03-09 17:16

关键是不能用vec;

--
👇
93996817

作者 sstudioer 2021-03-09 17:16

这也太复杂;

--
👇
12101111: 加一个Option

93996817 2021-03-09 17:01
参考下
use std::rc::Weak;
use std::cell::RefCell;
use std::rc::Rc;
struct School {
    name: String,
classes: RefCell<Vec<Weak<Class>>>,
}
struct Class {
    name: String,
    school: std::rc::Rc<School>,
}
pub fn main(){

    let school=Rc::new(School{ name: "S1".into(), classes:RefCell::new(vec![])});
    let class1=Rc::new(Class{ name: "c1".into(), school:Rc::clone(&school)});
    let class2=Rc::new(Class{ name: "c2".into(), school:Rc::clone(&school)});
    {
        let mut classes = school.classes.borrow_mut();
        classes.push(Rc::downgrade(&class1));
        classes.push(Rc::downgrade(&class2));
    }
    for week_cls in school.classes.borrow().iter() {
        if let Some(cls)=week_cls.upgrade(){
            println!("school class name={} school name= {}",cls.name,cls.school.name);
        }
    }
    println!("class name={} school name= {}",class1.name,class1.school.name);
    println!("class name={} school name= {}",class2.name,class2.school.name);

12101111 2021-03-09 16:57

加一个Option

uno 2021-03-09 15:49

先想想一个空值是什么样的吧

1 共 13 条评论, 1 页