拥有一些数据和对该数据的引用的结构

Kor*_*nel 6 object-lifetime rust borrow-checker

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

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

    Obj {
        original: data,
        processed: AnotherObj {
            reference: &data
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

在这里,我想要ObjAnotherObj并且data拥有相同的生命周期,当然还没有new()通话。

mdu*_*dup 13

基于您的要求的原始结构设计可能如下所示:

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 --+
}
Run Code Online (Sandbox Code Playgroud)

但是,开始工作非常棘手(就我个人而言,我无法做到),因为您希望'ainAnotherObj<'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)`
Run Code Online (Sandbox Code Playgroud)

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(),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

  • 一旦您移动“Obj”,原始指针选项就会崩溃。在您的代码示例中,只要您从 `new` 返回 `Obj`。通过优化,`new` 实际上可能会初始化一个由调用者分配的 `Obj`,这会给你一种它可以工作的错觉,但我还没有测试过。您必须将 `Obj` 装箱以给它一个固定地址,但 Rust 不会阻止您将 `Obj` 移出盒子。 (6认同)

归档时间:

查看次数:

4011 次

最近记录:

10 年,10 月 前