Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 为什么';难道不是一种从自我改变到不变的可变借用吗?_Rust_Borrow Checker - Fatal编程技术网

Rust 为什么';难道不是一种从自我改变到不变的可变借用吗?

Rust 为什么';难道不是一种从自我改变到不变的可变借用吗?,rust,borrow-checker,Rust,Borrow Checker,此代码使可怕的借用检查器()失败: 由于实现了非词汇生存期,因此触发错误需要这样做: fn main() { let mut dat = Data { a: 1, b: 2, c: 3 }; let aref = dat.reference_to_a(); let b = dat.get_b(); println!("{:?}, {}", aref, b); } 错误: error[E0502]:无法将'dat'作为不可变项借用,因为它也是作为可变项借用的 --

此代码使可怕的借用检查器()失败:

由于实现了非词汇生存期,因此触发错误需要这样做:

fn main() {
    let mut dat = Data { a: 1, b: 2, c: 3 };
    let aref = dat.reference_to_a();
    let b = dat.get_b();
    println!("{:?}, {}", aref, b);
}
错误:

error[E0502]:无法将'dat'作为不可变项借用,因为它也是作为可变项借用的
--> :19:20
|
18 |设aref=dat.reference_to_a();
|---可变借用发生在此处
19 | println!(“{}”,dat.get_b());
|^^^此处发生不可变借用
20 | }
|-可变借用结束于此

为什么会这样?当
reference\u to_a()
返回时,
dat
的可变借用被转换为不可变借用,因为该函数只返回不可变引用。借钱的人还不够聪明吗?这是计划吗?有办法解决吗?

生命周期与引用是否可变是分开的。通过代码工作:

fn reference_to_a(&mut self) -> &i32
虽然省略了寿命,但这相当于:

fn reference_to_a<'a>(&'a mut self) -> &'a i32
fn参考到i32
i、 e.输入和输出寿命相同。这是向这样的函数分配生存期的唯一方法(除非它返回了对全局数据的
&'static
引用),因为您不能从无到有地弥补输出生存期

这意味着,如果通过将返回值保存在变量中使其保持活动状态,那么
&mut self
也将保持活动状态

另一种思考方式是,
&i32
&mut self
的子借用,因此只在到期之前有效

正如@aSpex所指出的,这就是。

为什么这是一个错误:虽然@Chris在大约2.5年前已经给出了更精确的解释,但您可以将
fn reference\u to_a(&mut self)->&i32
作为一个声明来阅读:

“我想独占借用
self
,然后返回一个共享/不可变引用,该引用的有效期与原始独占借用相同”()

显然

借阅检查程序还不够聪明吗?这是计划好的吗?

仍然无法表达“我想在通话期间完全借用self,并在单独的生命周期内返回一个共享引用”。正如@aSpex所指出的,截至2018年底,该公司已被列为最受欢迎的公司之一

像以前一样,我找不到解决这个问题的具体计划。允许单独读/写“终身角色”(
Ref2
)的想法是,但据我所知,还没有人将其变成自己的RFC

是否有办法解决此问题?不太可能,但根据您首先需要此功能的原因,其他结构化代码的方法可能是合适的:

  • 您可以返回副本/克隆,而不是引用
  • 有时您可以将
    fn(&mut self)->&T
    分为两部分,一部分接受
    &mut self
    ,另一部分返回
    &T
  • 就像生锈一样,重新排列结构会有所帮助
  • 您可以从以下方法返回共享引用:
    fn(&mut-self)->(&self,&T)
    ()
  • 您可以使fn采用共享的
    &self
    引用和使用(即定义
    self
    中需要变异为
    单元格
    RefCell
    )的部分)。这可能感觉像是作弊,但实际上是适当的,例如,当你需要可变性作为目标的原因时。毕竟,我们正在制作一个方法,将
    &mut self
    转换为

。这完全是同一种情况。@Stargateur:我不认为“去糖化”代码是用来编译的;这只是为了说明。@Stargateur:不,这没用。有必要限制
贷款的生命周期
@aSpex:啊,是的,看起来是一样的。但是文档没有提出解决方案或解决方法?哦,事实上“根据我们实际关心的引用语义,这个程序显然是正确的,但是生命周期系统太粗了,无法处理它。”。因此,唯一的解决方案是使用独立的作用域@aSpex您应该发布答案。谢谢,有解决方案或解决方法吗?非词汇生存期能解决这个问题吗?我认为除了将变异分解成一个单独的方法调用之外,没有其他解决方法。这不是一件终生难忘的事情;
&i32
是从
&mut self
借来的,因此它们基本上是联系在一起的。@timmm OP示例在启用NLL时按原样工作。“示例在启用NLL时按原样工作”只是因为
aref
未使用。如果你使用它,比如
println!(“{}{}”,aref,dat.get_b())
那么NLL将不会有任何帮助,正如@ChrisEmerson所解释的。有没有原因可以解释为什么rust不能扩展到允许这样做,或者甚至为什么很难允许这样做。例如,为什么rust不能在返回时将可变的自我借用“降级”为不变的自我借用。这样,它就可以工作了(因为您可以对同一事物进行多个不可变的借用)。
fn reference_to_a<'a>(&'a mut self) -> &'a i32