Course Builder个人学习工作台 · 本地模式
Rust:从所有权到可测试的命令行工具

11|生命周期:表达返回引用来自哪里

目标:为返回输入片段的函数写出正确的生命周期关系,并识别不能返回局部引用的情况。

TextLab 的统计结果只有整数,不需要引用输入继续存活。但如果增加“显示最长的一行”,为了避免复制文本,我们可能想返回原输入的一段 &str。此时函数签名必须让编译器知道输出引用依赖哪个输入。

生命周期标注描述引用有效期之间的关系,不会延长对象寿命,也不会产生运行时计时器。单输入引用的常见函数可以省略标注;有多个输入引用,而且输出可能来自任意一个时,通常需要明确关系。'a 是生命周期参数名,可以换成其他名字。

在两个借来的片段之间选择

创建 examples/lifetimes.rs:

fn longer<'a>(left: &'a str, right: &'a str) -> &'a str {
    if left.len() >= right.len() {
        left
    } else {
        right
    }
}

fn main() {
    let left = String::from("rust");
    {
        let right = String::from("ownership");
        let chosen = longer(&left, &right);
        println!("chosen={chosen}");
    }
    println!("left={left}");
}

这里的“longer”按字节长度比较,刻意使用 ASCII,避免把 Unicode 统计单位混进借用实验。'a 表示两个输入都必须在输出被使用的那段期间有效;调用时可以把较长的有效期缩短到共同可用的范围,并不是要求两个原始变量同时创建、同时销毁。

运行前先预测:内层大括号结束后,哪些字符串仍被拥有?

cargo run --quiet --example lifetimes

预期输出:

chosen=ownership
left=rust

chosen 的使用发生在 right 被丢弃之前,所以有效。内层结束后 right 被丢弃,外层的 left 仍然存在。

有意让引用越过拥有者的边界

  1. 在内层大括号之前声明 let chosen;。
  2. 把内层的 let chosen = ... 改为 chosen = ...,并把打印 chosen 的语句移到内层大括号之后。
  3. 运行 cargo check --example lifetimes,预期失败,通常提示 right does not live long enough(E0597)。
  4. 恢复主示例。即使把 left 改得更长,签名仍允许返回 right,调用者必须遵守签名给出的关系。

独立练习:如果选择结果必须在两个输入销毁后仍然使用,把函数改成返回 String。只复制最终被选中的内容,不在比较之前克隆两个输入。

完整参考实现
fn longer_owned(left: &str, right: &str) -> String {
    let chosen = if left.len() >= right.len() { left } else { right };
    chosen.to_owned()
}

fn main() {
    let chosen;
    {
        let left = String::from("rust");
        let right = String::from("ownership");
        chosen = longer_owned(&left, &right);
    }
    assert_eq!(chosen, "ownership");
    println!("chosen={chosen}");
}

替换实验文件运行,预期 chosen=ownership。to_owned() 把借用的 str 复制为拥有的 String;它的存活期不再依赖输入,因此函数返回类型不需要生命周期参数。

如果想返回函数内 String 的引用,加任意 'a 都不能解决拥有者已经销毁的问题,应返回拥有值或借用调用者提供的数据。如果你想随手改成 &'static str,它要求引用可在整个程序运行期间有效,通常不能由运行时新建的局部字符串满足。先决定数据由谁保存,再写标注,顺序不能颠倒。

本课新增 examples/lifetimes.rs。下一课落地的 Report 只保存整数,主动避免让统计结果绑定输入的生命周期。

参考资料