Struct that owns some data and a data reference

Constructing an object extracts the data that is needed for that object to live, but also creates another object that needs to maintain data references:

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

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

      

Can this be expressed in terms of rust?

Here I would like to Obj

, AnotherObj

and data

have the same life span and, of course, experience the challenge new()

.

+3


source to share


1 answer


The raw design of structures based on your requirements might look like this:

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

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

      

However, it is very difficult to get a job (I personally could not) because you want 'a

to AnotherObj<'a>

was a time of life original

. However, you have to specify a lifetime Obj<'a>

, and you will need to indicate Obj<'tbc>

where 'tbc

is the lifetime of the item being created Obj

.

I suggest the following options:

1. Make AnotherObj truly original

Why not? Obj

will be owned AnotherObj

, so it can still be accessed 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. General construction of the pointer

Direct 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 original pointers

Options 1 and 2 will bring you the peace of mind of the harmless gods of rust, so I don't recommend this third option. I am still posting it here for completeness. Note: it compiles, but I've never tested it at runtime, so it might bite. There's only safe code below, but you'll need to step into the scope unsafe

if you want to dereference a 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
}

      

+3


source







All Articles