我有一些包含一些数据的 struct ,看起来像这样:

struct A {
    // Some data
}

struct B<'s> {
    a: &'s mut A
    c: C<'s>
}

impl<'s> B<'s> {
    fn new(a: &'s mut A, d: &'s D) -> B<'s> {
        let c = C::new(d);
        B { a, c }
    }

    fn extract_c(self) -> C<'s> {
        self.c
    }
}

// A smart pointer provided by a library
struct C<'s> {
    d: &'s D,
    // Other fields holding some data, not referencing A
}

struct D {
    // Some other data not referencing A in any way (provided by a library)
}

我也有创建和修改所述 struct 的函数,如下所示:

fn modify(b: &mut B) {
    // Modifies b.a and b.c
}

fn construct_c<'s>(a: &'s mut A, d: &'s D) -> C<'s> {
    let mut b = B::new(a, d); // C is created in B::new
    modify(&mut b);
    b.extract_c()
}

我想在其他地方使用construct_c,以便在从调用中获得结果后可以再次引用A,如下所示:

fn main() {
    let mut a = A::new();
    let d = D::new();
    let c = construct_c(&mut a, &d);  // First mutable borrow of `a`
    println!("{a}");   // Second borrow of `a`
    let result = do_sth_with_c(c);  // Move of `c`
    do_sth_with_a(a);
    // Some other code...
}

然而,当我try 这样做时,编译器告诉我,当我调用do_sth_with_c时,我使用的是a的第一个可变借入,尽管c没有保存提供给construct_c的对a的引用.

当我删除println!("{a}");do_sth_with_a时,代码会编译,但我确实需要打印该信息,并在呼叫do_sth_with_c之前打印出来.有没有办法告诉编译器Ca的引用一无所知,并且在调用construct_c之后可以安全地进行新的引用?

EDIT 1: 当我将所有引用&mut A替换为Rc<RefCell<A>>时,代码编译.但是有没有其他不用RcRefCell的方法呢?

一百零二 在this answer岁之后,B岁再活一年似乎就解决了这个问题.

How 100 changed:

struct B<'a, 's> {
    a: &'a mut A,
    c: C<'s>,
}

// All functions that use `B` need to be updated as well

推荐答案

你在一条关于C的 comments 中写道,"其他一些数据没有以任何方式引用A".但是,通过使用相同的生命周期,您可以告诉编译器它们是相关的.因此,将您的定义从

struct B<'s> {
    a: &'s mut A
    c: C<'s>
}

fn construct_c<'s>(a: &'s mut A, d: &'s D) -> C<'s> {
    let mut b = B::new(a, d);
    modify(&mut b);
    b.extract_c()
}

struct B<'s, 'c> {
    a: &'s mut A
    c: C<'c>
}

fn construct_c<'s, 'c>(a: &'s mut A, d: &'c D) -> C<'c> {
    let mut b = B::new(a, d);
    modify(&mut b);
    b.extract_c()
}

Now each lifetime can vary independently, and in particular, the 'c lifetime is allowed 到 be longer than 's.

That said, I have 到 warn you that you may be trying 到 use references where owned data would be better. A common beginner mistake is 到 try 到 build data s到rage structures out of references, and this is usually not a good idea because it either turns out impossible, or highly constrains how the structure can be used.

Rust相关问答推荐

Rust,polars CSV:有没有一种方法可以从impll BufRead(或任何字节迭代器)中读取CSV?

阻止websocket中断的中断中断的终端(操作系统错误4)

为什么幻影数据不能自动推断?

访问Rust中的隐藏变量

如果A == B,则将Rc A下推到Rc B

有没有办法模仿对象安全克隆?

Rust编译器似乎被结果类型与anyhow混淆

解析程序无法在Cargo 发布中 Select 依赖版本

rust中的库插件管理器,现在是否可行?

为相同特征的特征对象使用 move 方法实现特征

为什么实现特征的对象期望比具体对象有更长的生命周期?

在 Rust 中,在第一个空格上分割字符串一次

为什么需要同时为值和引用实现`From`?方法不应该自动解引用或borrow 吗?(2023-06-16)

枚举的利基优化如何在 Rust 中工作?

Rust 中函数的类型同义词

改变不实现克隆的 dioxus UseState struct

如何存储返回 Future 的闭包列表并在 Rust 中的线程之间共享它?

Rust 内联 asm 中的向量寄存器:不能将 `Simd` 类型的值用于内联汇编

如何创建动态创建值并向它们返回borrow 的工厂?

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?