Struct that owns some data and a reference to the data [duplicate]

淺唱寂寞╮ 提交于 2019-12-19 02:20:22

问题


Construction of an object allocates data needed for lifetime of that object, but also creates another object that needs to keep references to the data:

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

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

Is it possible to express this in Rust's terms?

Here I'd like Obj, AnotherObj and data to have the same lifetime, and of course outlive the new() call.


回答1:


A raw design of the structs based on your requirements might look like this:

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 --+
}

However it's very tricky to get working (personally, I wasn't able to) because you want the 'a in AnotherObj<'a> to be the lifetime of original. However you must supply a lifetime to Obj<'a> and thus you would have to specify Obj<'tbc> where 'tbc is the lifetime of the Obj to be created.

I suggest the following alternatives:

1. Make AnotherObj actually own the original

Why not? Obj will own AnotherObj, so it can still have access to original as a nested child:

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. Shared pointer design

Straightforward use of refcounted pointers:

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. With raw pointers

Options 1. and 2. will bring you the peace of mind of the safe Rust gods, therefore I don't recommend this third option. I still post it here for completeness. Note: it compiles, but I never tested it at runtime, so it may bite. There's only safe code below but you'll have to go in unsafe land when you want to dereference the raw pointer.

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
}


来源:https://stackoverflow.com/questions/30823880/struct-that-owns-some-data-and-a-reference-to-the-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!