结论:Rust 通过借用检查器(borrow checker)在编译期验证:每个引用的生命周期都不能超出其指向数据的存活范围,一旦发现引用可能比数据活得更久(即悬垂引用)就直接编译失败,从语言层面消灭这类未定义行为。
展开:最典型的是函数返回局部变量的引用——局部变量在函数返回时即被释放,返回的引用必然悬垂,编译器拒绝通过。借用检查器为每个引用推导生命周期,要求"被借用的值至少活得和引用一样久";跨函数场景需要用生命周期标注把输入输出引用的关系告诉编译器,由它在调用点检查。易错点:新手常试图用返回引用来"避免拷贝",正确做法是返回拥有所有权的值(String 而非 &str),或借用调用方传入的数据。追问方向:借用检查器保守吗?是的,它只接受可证明安全的代码,NLL 已大幅减少误报,Polonius 会进一步改进。
fn dangle() -> &String { // 编译错误:缺生命周期且 s 会被释放
let s = String::from("x");
&s // s 在函数结束时被释放
}
fn ok() -> String { String::from("x") } // 返回所有权