为了账号安全,请及时绑定邮箱和手机立即绑定

为什么借用临时工是合法的?

/ 猿问

为什么借用临时工是合法的?

C++
春华秋衣 2019-10-21 15:47:27

来自C ++,我很惊讶该代码在Rust中有效:


let x = &mut String::new();

x.push_str("Hello!");

在C ++中,您不能使用临时地址,并且临时地址不会超出其出现的表达式的寿命。


临时工在Rust居住多长时间?而且由于x只有借用,字符串的所有者是谁?


查看完整描述

3 回答

?
慕丝7291255

为什么借用临时工是合法的?


出于同样的原因它是合法的,因为它在C ++中是非法的- 因为有人说应该这样做。


临时工在Rust居住多长时间?而且由于x只有借用,字符串的所有者是谁?


参考资料说:


临时值的寿命通常是


最内在的陈述;块的尾部表达式被视为包围该块的语句的一部分,或者

条件表达式或循环条件表达式(如果在an if或  if/ else的loop条件表达式或while表达式的条件表达式中创建了临时表达式)。

但是,当创建分配给let 声明的临时右值时,将使用封闭块的生存期来创建该临时右值,因为使用封闭语句(该let 声明)将确保出现错误(因为指向临时块的指针)将被存储到变量中,但在使用该变量之前将释放临时变量)。编译器使用简单的语法规则来决定将哪些值分配给let绑定,因此应获得更长的临时寿命。


本质上,您可以将代码视为:


let mut a_variable_you_cant_see = String::new();

let x = &mut a_variable_you_cant_see;

x.push_str("Hello!");


查看完整回答
反对 回复 2019-10-21
?
烧仙草VB

Rust的MIR提供了有关临时人员性质的一些见解;考虑以下简化情况:


fn main() {

    let foo = &String::new();

}

及其产生的MIR(用我的标准注释代替):


fn main() -> () {

    let mut _0: ();

    scope 1 {

        let _1: &std::string::String; // the reference is declared

    }

    scope 2 {

    }

    let mut _2: std::string::String; // the owner is declared


    bb0: {                              

        StorageLive(_1); // the reference becomes applicable

        StorageLive(_2); // the owner becomes applicable

        _2 = const std::string::String::new() -> bb1; // the owner gets a value; go to basic block 1

    }


    bb1: {

        _1 = &_2; // the reference now points to the owner

        _0 = ();

        StorageDead(_1); // the reference is no longer applicable

        drop(_2) -> bb2; // the owner's value is dropped; go to basic block 2

    }


    bb2: {

        StorageDead(_2); // the owner is no longer applicable

        return;

    }

}

您可以看到,“不可见”的所有者在将引用分配给它之前已收到一个值,并且按预期的那样,该引用已在所有者之前被删除。


我不确定的是为什么会有看似无用的东西scope 2,为什么所有者没有放在任何范围内?我怀疑MIR尚未100%准备就绪。


查看完整回答
反对 回复 2019-10-21
?
喵喔喔

从Rust参考:


临时寿命


在大多数场所表达式上下文中使用值表达式时,会创建一个临时的未命名内存位置,并初始化为该值,然后表达式求值至该位置


这是适用的,因为它String::new()是一个值表达式,而在&mut它下面是一个位置表达式上下文。现在,引用运算符只需要通过此临时存储位置,因此它成为整个右侧(包括&mut)的值。


但是,当创建分配给let声明的临时值表达式时,将使用封闭块的生存期来创建临时值表达式


由于已将其分配给变量,因此它的生存期一直到封闭块结束为止。


这也回答了这个问题有关的区别


let a = &String::from("abcdefg"); // ok!


let a = String::from("abcdefg").as_str(); // compile error

在第二个变体中,临时变量传递给as_str(),因此其生存期在语句末尾结束。


查看完整回答
反对 回复 2019-10-21

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信