无法使用if表达式附加到字符串而不是if语句

时间:2018-10-30 19:07:12

标签: string rust borrow-checker borrowing

我有以下运行良好的代码:

fn main() {
    let mut example = String::new();

    if 1 + 1 == 2 {
        example += &"string".to_string()
    } else {
        example += &'c'.to_string()
    };

    println!("{}", example);
}

当我将代码更改为此:

fn main() {
    let mut example = String::new();

    example += if 1 + 1 == 2 {
        &"string".to_string()
    } else {
        &'c'.to_string()
    };

    println!("{}", example);
}

我收到以下错误:

error[E0597]: borrowed value does not live long enough
 --> src/main.rs:5:10
  |
5 |         &"string".to_string()
  |          ^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
6 |     } else {
  |     - temporary value dropped here while still borrowed
7 |         &'c'.to_string()
8 |     };
  |     - temporary value needs to live until here

error[E0597]: borrowed value does not live long enough
 --> src/main.rs:7:10
  |
7 |         &'c'.to_string()
  |          ^^^^^^^^^^^^^^^ temporary value does not live long enough
8 |     };
  |     - temporary value dropped here while still borrowed
  |
  = note: values in a scope are dropped in the opposite order they are created

这对我来说毫无意义,因为两个代码片段看起来都是相同的。为什么第二个片段不起作用?

2 个答案:

答案 0 :(得分:4)

您有already seen an explanation as to why this code cannot be compiled。这是一些有效且更接近您目标的代码:

hypothesis

我不会说这是惯用的Rust。我遇到的一件事是将example += &if 1 + 1 == 2 { "string".to_string() } else { 'c'.to_string() }; 不必要地分配到"string"中。我将使用String::push_strString::push编写这段代码:

String

如果您不附加字符串,我将直接对其进行评估:

if 1 + 1 == 2 {
    example.push_str("string");
} else {
    example.push('c');
}

我什至可以使用动态调度(尽管可能性较小):

let example = if 1 + 1 == 2 {
    "string".to_string()
} else {
    'c'.to_string()
};

let s: &std::fmt::Display = if 1 + 1 == 2 { &"string" } else { &'c' };
let example = s.to_string();

另请参阅:

答案 1 :(得分:3)

&应用于表达式时,Rust自动创建拥有该表达式求值结果的匿名变量。因此,您的代码大致相当于

fn main() {
    let mut example = String::new();

    example += if 1 + 1 == 2 {
        let temp1 = "string".to_string();
        &temp1
    } else {
        let temp2 = 'c'.to_string();
        &temp2
    };

    println!("{}", example);
}

您现在希望可以清楚地看到,temp1的范围(和生存期)仅限于true表达式的if分支,以及{ {1}}仅限于temp2表达式的false分支。范围/生存期均未扩展到if表达式之外,因此if的两个分支内的String不能附加到if

相反,您的第一个示例大致等于

example

,并且在两种情况下,fn main() { let mut example = String::new(); if 1 + 1 == 2 { let temp1 = "string".to_string(); example += &temp1; } else { let temp2 = 'c'.to_string(); example += &temp2; }; println!("{}", example); } temp1的寿命都足够长,因此可以复制temp2的内容并将其附加到String之前的exampletemp1被删除。