拥有一些数据和对数据的引用的Struct

时间:2015-06-13 21:48:13

标签: rust object-lifetime borrow-checker

构造对象会分配该对象生命周期所需的数据,但也会创建另一个需要保持对数据的引用的对象:

pub fn new() -> Obj {
    let data = compute();

    Obj {
        original: data,
        processed: AnotherObj {
            reference: &data
        }
    }
}

是否可以用Rust的术语表达这一点?

我希望ObjAnotherObjdata拥有相同的生命周期,当然比new()电话更长。

1 个答案:

答案 0 :(得分:4)

根据您的要求对结构进行原始设计可能如下所示:

struct AnotherObj<'a> {
    original: &'a Vec<i8>, // Let's agree on Vec<i8> as your "data" type.
}

struct Obj<'a> {
    original: Vec<i8>,         // <-------------------+
    processed: AnotherObj<'a>, // should point here --+
}

然而,开始工作(个人而言,我无法工作)非常棘手,因为您希望'a中的AnotherObj<'a>成为original的生命周期。但是,您必须为Obj<'a>提供生命周期,因此您必须指定Obj<'tbc>,其中'tbc是要创建的Obj的生命周期。

我建议以下替代方案:

1。让AnotherObj实际上拥有原始

为什么不呢? Obj将拥有AnotherObj,因此它仍然可以作为嵌套子项访问original

pub struct AnotherObj {
    original: Vec<i8>,
}

pub struct Obj {
    processed: AnotherObj,
}

pub fn new() -> Obj {
    let data = vec![1,2,3];

    Obj {
        processed: AnotherObj {
            original: data,
            // ...
        }
    }
}

// access as obj.processed.original, you can even create a getter `fn original(&self)`

2。共享指针设计

直接使用refcounted指针:

use std::rc::Rc;

pub struct AnotherObj {
    original: Rc<Vec<i8>>,
}

pub struct Obj {
    original: Rc<Vec<i8>>,
    processed: AnotherObj,
}

pub fn new() -> Obj {
    let data = Rc::new(vec![1,2,3]);

    Obj {
        original: data.clone(),
        processed: AnotherObj {
            original: data.clone(),
        }
    }
}

3。使用原始指针

选项1.和2.将为您带来安全的Rust神的安心,因此我不建议这第三个选项。我仍然在这里发布完整性。注意:它编译,但我从未在运行时测试它,所以它可能会咬人。下面只有安全代码,但是当你想取消引用原始指针时,你必须进入unsafe

use std::ptr;

pub struct AnotherObj {
    original: *mut Vec<i8>,
}

pub struct Obj {
    original: Vec<i8>,
    processed: AnotherObj,
}

pub fn new() -> Obj {
    let data = vec![1,2,3];

    let mut obj = Obj {
        original: data,
        processed: AnotherObj {
            original: ptr::null_mut(),
        }
    };
    obj.processed.original = &mut obj.original as *mut Vec<i8>;

    obj
}