我想用 Rust 编写这个 C++ 的等价物:
struct Bar { int x; };
struct Foo { Bar* bar; };
void main() {
Bar bar { 42 };
Foo foo { &bar };
Bar bar2 { 50 };
foo.bar = &bar2;
printf("%d\n", foo.bar->x);
}
C++ 建立一个结构,然后用另一个 Bar
对象交换一个 Bar
对象。这是我试过的代码:
struct Bar(isize);
impl Bar {
fn new(i: isize) -> Bar { Bar(i) }
}
struct Foo<'a> {
bar: Option<&'a Bar>,
}
impl<'a> Foo<'a> {
fn new(bar: &Bar) -> Foo {
Foo { bar: Some(&bar) }
}
}
fn main() {
// Set up first state
let bar = Bar::new(42);
let mut foo = Foo::new(&bar);
// Replace bar object
let bar2 = Bar::new(50);
foo.bar = Some(&bar2);
if let Some(e) = foo.bar {
println!("{}", e.0);
}
}
此代码提示:
error[E0597]: `bar2` does not live long enough
--> src/main.rs:22:21
|
22 | foo.bar = Some(&bar2);
| ^^^^ borrowed value does not live long enough
...
27 | }
| - `bar2` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
在 Rust 中是否可能有一个结构引用了一个生命周期可以更短的子结构(即,您可以用另一个实例替换子结构实例)?
我看了一些其他答案,并尝试拆分结构:
struct Bar(isize);
impl Bar {
fn new(i: isize) -> Bar {
Bar(i)
}
}
struct FooCore {
a: isize,
}
struct Foo<'c, 'a> {
core: &'c FooCore,
bar: &'a Bar,
}
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c FooCore, bar: &'a Bar) -> Foo<'c, 'a> {
Foo {
core: &core,
bar: &bar,
}
}
}
fn main() {
// Set up first state
let core = FooCore { a: 10 };
let bar = Bar::new(42);
let _foo = Foo::new(&core, &bar);
// Replace bar object
let bar2 = Bar::new(50);
let foo = Foo::new(&core, &bar2);
println!("{} {}", foo.core.a, foo.bar.0);
}
这可以编译并工作,但是,一旦我将 core 和 bar 字段设置为可变,它就会崩溃。下面是使用 mut
的代码:
#![allow(unused_mut)]
struct Bar(isize);
impl Bar {
fn new(i: isize) -> Bar {
Bar(i)
}
}
struct FooCore {
a: isize,
}
struct Foo<'c, 'a> {
core: &'c mut FooCore,
bar: &'a mut Bar,
}
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c mut FooCore, bar: &'a mut Bar) -> Foo<'c, 'a> {
Foo {
core: &mut core,
bar: &mut bar,
}
}
}
fn main() {
// Set up first state
let mut core = FooCore { a: 10 };
let mut bar = Bar::new(42);
let mut _foo = Foo::new(&mut core, &mut bar);
// Replace bar object
let mut bar2 = Bar::new(50);
let mut foo = Foo::new(&mut core, &mut bar2);
println!("{} {}", foo.core.a, foo.bar.0);
}
这会导致错误:
error[E0597]: `core` does not live long enough
--> src/main.rs:21:24
|
21 | core: &mut core,
| ^^^^ borrowed value does not live long enough
...
24 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'c as defined on the impl at 18:1...
--> src/main.rs:18:1
|
18 | impl<'c, 'a> Foo<'c, 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0597]: `bar` does not live long enough
--> src/main.rs:22:23
|
22 | bar: &mut bar,
| ^^^ borrowed value does not live long enough
23 | }
24 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 18:1...
--> src/main.rs:18:1
|
18 | impl<'c, 'a> Foo<'c, 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0499]: cannot borrow `core` as mutable more than once at a time
--> src/main.rs:35:33
|
31 | let mut _foo = Foo::new(&mut core, &mut bar);
| ---- first mutable borrow occurs here
...
35 | let mut foo = Foo::new(&mut core, &mut bar2);
| ^^^^ second mutable borrow occurs here
...
38 | }
| - first borrow ends here
我如何构建我的数据以实现我想要的?
最佳答案
明显的问题是您不必要地引用了引用:
在这段代码中,core
和bar
已经是引用了,所以不需要获取它的地址:
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c mut FooCore, bar: &'a mut Bar) -> Foo<'c, 'a> {
Foo {
core: &mut core,
bar: &mut bar,
}
}
}
改为:
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c mut FooCore, bar: &'a mut Bar) -> Foo<'c, 'a> {
Foo {
core: core,
bar: bar,
}
}
}
关于子对象的生命周期比主对象长,一般的回答是“不,你不能”,因为引用可能会悬空而 Rust 不允许这样做。有一些解决方法,如上面评论中的链接答案所示。
作为模拟 C 代码的额外解决方法,您可以编写:
fn main() {
// Set up first state
let mut core = FooCore { a: 10 };
let mut bar = Bar::new(42);
let mut bar2; //lifetime of bar2 is greater than foo!
let mut foo = Foo::new(&mut core, &mut bar);
bar2 = Bar::new(50); //delayed initialization
// Replace bar object
foo.bar = &mut bar2;
println!("{} {}", foo.core.a, foo.bar.0);
}
关于rust - 是否有可能有一个结构引用了一个生命周期可以更短的子结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50591935/