gpt4 book ai didi

rust - 可变借用以解决结构持有引用问题

转载 作者:行者123 更新时间:2023-11-29 07:57:47 25 4
gpt4 key购买 nike

我遇到了作为可变引用传递的结构的问题。仅当结构被定义为保存引用时才会出现此问题。

struct Global<'a> {
one: i32,
two: &'a i32
}

fn do_task<'a, F, R: 'a>(global: &'a mut Global<'a>, task: F)
where F: Fn(&'a mut Global<'a>) -> &'a R {
let result = task(global);
}

fn one<'a>(global: &'a mut Global<'a>) -> &'a i32 {
&global.one
}

fn two<'a>(global: &'a mut Global<'a>) -> &'a i32 {
global.two
}

fn main() {
let number = 2;
let mut global = Global {
one: 1,
two: &number
};
do_task(&mut global, one);
do_task(&mut global, two);
}

借用检查员提示如下:

error: cannot borrow `global` as mutable more than once at a time
do_task(&mut global, two);
^~~~~~
note: previous borrow of `global` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `global` until the borrow ends
do_task(&mut global, one);
^~~~~~
note: previous borrow ends here
fn main() {
...
}
^

但是,如果我更改代码以使字段 two 不是引用,如下例所示,那么它会通过。

struct Global {
one: i32,
two: i32,
}

fn do_task<'a, F, R: 'a>(global: &'a mut Global, task: F)
where F: Fn(&'a mut Global) -> &'a R {
let result = task(global);
}

fn one<'a>(global: &'a mut Global) -> &'a i32 {
&global.one
}

fn two<'a>(global: &'a mut Global) -> &'a i32 {
&global.two
}

fn main() {
let mut global = Global {
one: 1,
two: 2
};
do_task(&mut global, one);
do_task(&mut global, two);
}

我尝试用另一个作用域包围 do_task 函数调用,但没有效果。

为什么让引用将可变借用扩展到 main 的末尾,有什么办法解决这个问题吗?

我正在使用 rustc 1.0.0 (a59de37e9 2015-05-13)(内置 2015-05-14)

最佳答案

问题是你不小心绑在一起了Global的通用生命周期参数和可变借用的生命周期。

当你需要&'a mut Global<'a> ,这意味着 Global 的可变借用的持续时间 |必须与 two 中的引用一样长——因此,Global 的全长的存在。因此,您已经做出了被推断为永久借用 global 的事情。当你写 &mut global .我将以这种方式使用不太有效但可以理解要点的语法来编写它:

fn main() {
'a: {
let number: i32 + 'a = 2;
let mut global: Global<'a> = Global {
one: 1,
two: &'a number,
};
do_task(&mut global: &'a mut Global<'a>, one);
do_task(&mut global: &'a mut Global<'a>, two);
}
}

每个&mut global正在借global直到 'a 结束 block ,因此第二个与第一个发生冲突。

您希望分别对待这两个生命周期。该函数应该绑定(bind)一个生命周期参数,而不是使用具体的生命周期:这是 F: for<'b> Fn(&'b mut Global) -> &'b R像这样读:“F应该,给定一个任意的生命周期 'b , 实现 Fn(&'b mut Global) -> &'b R ”。然后将实际函数与生命周期参数一起写入 Global已删除,因此可以将其推断为另一个任意生命周期,如下所示:

fn one<'a>(global: &'a mut Global) -> &'a i32 {
&global.one
}

Here’s the final result:

struct Global<'a> {
one: i32,
two: &'a i32
}

fn do_task<F, R>(global: &mut Global, task: F)
where F: for<'a> Fn(&'a mut Global) -> &'a R {
let result = task(global);
}

fn one<'a>(global: &'a mut Global) -> &'a i32 {
&global.one
}

fn two<'a>(global: &'a mut Global) -> &'a i32 {
global.two
}

fn main() {
let number = 2;
let mut global = Global {
one: 1,
two: &number
};
do_task(&mut global, one);
do_task(&mut global, two);
}

关于rust - 可变借用以解决结构持有引用问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30497981/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com