【问题标题】:Struct that owns some data and a reference to the data [duplicate]拥有一些数据和对数据的引用的结构[重复]
【发布时间】:2015-08-29 16:36:36
【问题描述】:

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

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

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

可以用 Rust 的术语来表达吗?

在这里,我希望 ObjAnotherObjdata 拥有相同的生命周期,当然也比 new() 调用的寿命更长。

【问题讨论】:

  • 这里的问题和接受的答案都比“重复”更清楚。

标签: rust object-lifetime borrow-checker


【解决方案1】:

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

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

但是开始工作非常棘手(就我个人而言,我做不到),因为您希望AnotherObj&lt;'a&gt; 中的'a 成为original 的生命周期。但是,您必须为Obj&lt;'a&gt; 提供生命周期,因此您必须指定Obj&lt;'tbc&gt;,其中'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。共享指针设计

引用计数指针的直接使用:

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
}

【讨论】:

  • 只要移动Obj,原始指针选项就会崩溃。在您的代码示例中,只要您从new 返回Obj。通过优化,new 可能实际上会初始化一个由调用者分配的Obj,这会给你一种它有效的错觉,但我还没有对此进行测试。您必须将 Obj 装箱以提供固定地址,但 Rust 不会阻止您将 Obj 移出盒子。
猜你喜欢
  • 1970-01-01
  • 2016-06-14
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 2019-09-30
  • 1970-01-01
相关资源
最近更新 更多