gpt4 book ai didi

struct - 是否有可能有一个结构包含对生命周期比结构短的值的引用?

转载 作者:行者123 更新时间:2023-11-29 08:22:48 24 4
gpt4 key购买 nike

这是我要存档的简化版本:

struct Foo<'a> {
boo: Option<&'a mut String>,
}

fn main() {
let mut foo = Foo { boo: None };
{
let mut string = "Hello".to_string();
foo.boo = Some(&mut string);
foo.boo.unwrap().push_str(", I am foo!");
foo.boo = None;
} // string goes out of scope. foo does not reference string anymore

} // foo goes out of scope

这显然是完全安全的,因为一旦 string 超出范围,foo.boo 就是 None

有没有办法告诉编译器这个?

最佳答案

This is obviously completely safe

对人类来说显而易见的东西对编译器来说并不总是显而易见的;有时编译器不如人类聪明(但它更警惕!)。

在这种情况下,您的原始代码会在 non-lexical lifetimes 时编译。已启用:

#![feature(nll)]

struct Foo<'a> {
boo: Option<&'a mut String>,
}

fn main() {
let mut foo = Foo { boo: None };
{
let mut string = "Hello".to_string();
foo.boo = Some(&mut string);
foo.boo.unwrap().push_str(", I am foo!");
foo.boo = None;
} // string goes out of scope. foo does not reference string anymore

} // foo goes out of scope

只是因为foo一旦无效就永远不会被使用(在string超出范围之后),不是 因为您将该值设置为 None。尝试打印出最内层作用域之后的值仍然会导致错误。

Is it possible to have a struct which contains a reference to a value which has a shorter lifetime than the struct?

Rust 借用系统的目的是确保持有引用的事物不会比被引用的项目存活得更久。

非词法生命周期之后

也许吧,只要您不使用引用不再有效即可。这有效,例如:

#![feature(nll)]

struct Foo<'a> {
boo: Option<&'a mut String>,
}

fn main() {
let mut foo = Foo { boo: None };
// This lives less than `foo`
let mut string1 = "Hello".to_string();
foo.boo = Some(&mut string1);
// This lives less than both `foo` and `string1`!
let mut string2 = "Goodbye".to_string();
foo.boo = Some(&mut string2);
}

在非词法生命周期之前

没有。借用检查器不够智能,无法告诉您不能/不要在引用无效后使用它。它过于保守。

在这种情况下,您遇到了这样一个事实,即生命周期被表示为类型的一部分。换句话说,通用生命周期参数 'a 已经“填充”了一个具体的生命周期值,覆盖了 string 处于事件状态的行。但是,foo 的生命周期比那些行长,因此会出现错误。

编译器不会查看您的代码执行的操作;一旦它看到您用特定的生命周期对其进行参数化,它就是这样。


我通常会采用的解决方法是将类型分成两部分,需要引用的部分和不需要引用的部分:

struct FooCore {
size: i32,
}

struct Foo<'a> {
core: FooCore,
boo: &'a mut String,
}

fn main() {
let core = FooCore { size: 42 };
let core = {
let mut string = "Hello".to_string();
let foo = Foo { core, boo: &mut string };
foo.boo.push_str(", I am foo!");
foo.core
}; // string goes out of scope. foo does not reference string anymore

} // foo goes out of scope

请注意这如何消除了对 Option 的需求——您的类型现在会告诉您字符串是否存在。

另一种解决方案是在设置字符串时映射整个类型。在这种情况下,我们使用整个变量并通过更改生命周期来更改类型:

struct Foo<'a> {
boo: Option<&'a mut String>,
}

impl<'a> Foo<'a> {
fn set<'b>(self, boo: &'b mut String) -> Foo<'b> {
Foo { boo: Some(boo) }
}

fn unset(self) -> Foo<'static> {
Foo { boo: None }
}
}

fn main() {
let foo = Foo { boo: None };
let foo = {
let mut string = "Hello".to_string();
let mut foo = foo.set(&mut string);
foo.boo.as_mut().unwrap().push_str(", I am foo!");
foo.unset()
}; // string goes out of scope. foo does not reference string anymore

} // foo goes out of scope

关于struct - 是否有可能有一个结构包含对生命周期比结构短的值的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45713314/

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