我对Rust 还是个新手.我的简单代码

struct Foo<'a>{
    data : & 'a String,
}
fn test_foo(){
   let s1:String = String::from("A"); 
   let mut foo:Foo = Foo { data: & s1 };
   let s2:String = String::from("B");
   foo.data = & s2;  
}

我的问题是:如果我为Foo struct 实现DROP特征

foo.data = & s2; 

开始给出编译错误:s2生存时间不够长.这个错误在我看来是有道理的.但是,如果我没有为foo实现Drop特征,为什么我没有收到相同的错误

推荐答案

在Rust中,局部变量(来自相同作用域)以与定义顺序相反的顺序删除.

fn test_foo(){
   let s1:String = String::from("A"); 
   let mut foo:Foo = Foo { data: & s1 };
   let s2:String = String::from("B");
   foo.data = & s2;  
}

我们在这里按顺序声明三个局部变量:s1foos2.铁 rust 想要以相反的顺序丢弃它们:首先是s2,然后是foo,然后是s1.然而,生命周期有一个问题.一旦go 掉s2,那么foo.data就是uninitialized,也就是说它指向垃圾内存.

现在,为什么没有Drop也能行得通呢?铁 rust 有一个叫partial moves的概念.如果您的 struct 有多个字段,Rust将允许您移出某些字段,而不会使整个 struct 无效.原则上,如果我有一个

struct Person {
  name: String,
  age: i32,
  occupation: String,
}

我做let name = my_person.name;(其中my_person: Person),然后我从Person中移出一个值.因此,my_person.name是无效的,在没有部分移动的情况下,Rust应该认为my_person完全无效.但是,我们知道my_person.agemy_person.occupation仍然有效,所以拉斯特会让ageoccupation留在原地.它记得name被移动了(因此不应该被丢弃的垃圾),而ageoccupation仍然有效.

在您的示例中,同样的事情正在发生.铁 rust 想要下跌s2,但Foo仍然提到它.Ruust认为这很好:我们将go 掉s2,并简单地说Foo已经是partially moved:它的data字段不再有效.然后,当我们接下来删除foo时,我们不需要删除引用,只需要删除最外面的Foo层本身.

没有Drop个实例,这是很好的,铁 rust 将允许它.但是,如果impl<'a> Drop for Foo<'a>在作用域内,则Foo的部分移动为completely disabled.Rust看到您正在实现一些定制的Drop行为,现在它不允许部分初始化的对象存在,因为我们必须删除一个部分初始化的对象,并且Rust无法预测您的定制Drop代码将做什么或它将做出什么假设.

因此,对于Drop实现,Rust仍然希望首先删除s2,但它不能将引用部分移出foo,因为这会使foo处于部分初始化状态,这是不允许的.

Rust相关问答推荐

将JSON密钥转换为Polars DataFrame

如何容器化Linux上基于Rust的Windows应用程序的编译过程?

如何找到一个数字在二维数组中的位置(S)?

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

抽象RUST中的可变/不可变引用

当第二个`let`依赖于第一个`let()`时,如何在一行中有多个`let()`?

"value is never read警告似乎不正确.我应该忽略它吗?

不能在一个代码分支中具有不变的自身borrow ,而在另一个代码分支中具有可变的self borrow

为什么Rust不支持带关联常量的特征对象?

我如何使用AWS SDK for Rust获取我承担的角色的凭据?

失真图像图形捕获Api

有没有一种方法可以创建一个闭包来计算Rust中具有随机系数的n次多项式?

将泛型中的 Box 转换为 rust 中的 Box

我可以在 Rust 中 serde struct camel_case 和 deserde PascalCase

为什么具有 Vec 变体的枚举没有内存开销?

如何异步记忆选项中的 struct 字段

在单独的线程上运行 actix web 服务器

匹配结果时的简洁日志(log)记录

在 Rust 中退出进程

如何将 while 循环内的用户输入添加到 Rust 中的向量?