【问题标题】:Is there a way to have a struct contain a reference that might no longer be valid?有没有办法让结构包含可能不再有效的引用?
【发布时间】:2020-06-15 22:06:43
【问题描述】:

就像某种Box 持有对值的引用之类的?在读取它之前,我必须检查该值是否仍然存在,例如当 Option 与模式匹配时。

一个模拟示例:

struct Whatever {
    thing: AliveOrNot<i32>,
}
fn main() {
    let mut w = Whatever { thing: Holder::Empty };
    w.thing = AliveOrNot::new(100);
    match w.thing {
        Empty => println!("doesn't exist"),
        Full(value) => println!("{}", value),
    }
}

确切的情况是我正在使用 sdl2 Font 并且我想将该结构的实例存储在另一个结构中。我不想做这样的事情,因为Parent 必须和Font 一样长:

struct Font<'a, 'b> {
    aa: &'a i32,
    bb: &'b i32,
}
struct Parent<'a, 'b, 'c> {
    f: &'c Font<'a, 'b>
}

我想要的是让Parent 工作,无论该字段是否仍然存在。

【问题讨论】:

    标签: rust


    【解决方案1】:

    您可能对std::rc::Weakstd::sync::Weak 感兴趣:

    use std::rc::{Rc, Weak};
    
    struct Whatever {
        thing: Weak<i32>,
    }
    
    impl Whatever {
        fn do_it(&self) {
            match self.thing.upgrade() {
                Some(value) => println!("{}", value),
                None => println!("doesn't exist"),
            }
        }
    }
    
    fn its_dead_jim() -> Whatever {
        let owner = Rc::new(42);
        let thing = Rc::downgrade(&owner);
    
        let whatever = Whatever { thing };
        whatever.do_it();
    
        whatever
    }
    
    fn main() {
        let whatever = its_dead_jim();
        whatever.do_it();
    }
    
    42
    doesn't exist
    

    使用非'static 引用在安全的 Rust 中没有方法可以做到这一点。 Rust 引用的一大特点是不可能引用无效值。

    • 您可以泄漏内存,创建一个&amp;'static i32,但如果您需要多次这样做,这是不可持续的。

    • 您可以使用unsafe 代码并处理没有生命周期概念的原始指针。然后,您有责任确保不会引入内存不安全。

    另见:

    【讨论】:

    • 那么我将如何指定具有生命周期的类型呢?如果我执行play.rust-lang.org/… 之类的操作,Parent 结构是否必须与 Font 结构一样长?
    • @PabloTatoRamos 以该示例为例,Parent 不会被允许超过任何建立 'a'b 生命周期的时间,but the Font can be dropped
    • 我认为我们彼此不理解。 'a 和 'b 生命周期的存在是因为它们对 Font 有意义,而不是因为它们对 Parent 有意义。当这些生命结束时,我特别不想放弃 Parent。
    • @PabloTatoRamos 这不是您是否可以编写unsafe 代码来执行此操作的问题 - 这也是不健全。即使查看悬空指针也是未定义的行为,因此您最好的选择是使用 Weak,它专门用于模拟可能不再有效的引用的想法。
    • @Pablo 你不能有一个无效的引用,即使是在不安全的代码中。创建一个是即时UB。存在生命周期的原因就是为了证明这一点。听起来您对如何解决问题充其量只是一个模糊的想法; Rust 没有任何机制可以让Parent 被告知它应该失效,或者实际上任何机制可以让Parent 知道它 失效了。 引用始终有效。
    猜你喜欢
    • 2021-01-03
    • 2019-12-05
    • 1970-01-01
    • 2015-08-13
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    相关资源
    最近更新 更多