题目
实现返回较长字符串切片的函数
信息
- 类型:问答
- 难度:⭐
考点
生命周期注解, 函数签名, 引用有效性
快速回答
实现一个函数,接受两个字符串切片引用并返回较长的一个(长度相等时返回第一个)。需要显式添加生命周期注解确保引用有效性:
- 在函数签名中使用
'a标注输入和输出的生命周期 - 语法:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str - 生命周期注解保证返回的引用不会比输入引用存活更久
问题背景
在 Rust 中,当函数返回引用时,编译器需要明确知道返回的引用与输入参数的生命周期关系,以防止悬垂引用。本题要求实现一个比较两个字符串切片长度的函数,返回较长者的引用。
解决方案
正确实现需要显式声明生命周期参数:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}原理说明
- 生命周期注解
'a:定义一个生命周期参数,表明输入引用和输出引用拥有相同的生命周期约束 - 编译器行为:Rust 借用检查器会验证实际传入的引用是否满足
'a的生命周期要求 - 关键规则:返回的引用生命周期不能超过任一输入引用的生命周期
常见错误
// 错误示例:缺少生命周期注解
fn longest(x: &str, y: &str) -> &str { ... }
// 编译器报错:missing lifetime specifier- 错误原因:未明确返回引用与输入引用的生命周期关系
- 修正方案:按正确方案添加泛型生命周期参数
最佳实践
- 当函数返回引用且依赖输入参数时,必须声明生命周期参数
- 使用有意义的生命周期名称(如
'ctx,'data)提升可读性 - 多个参数有不同生命周期时,需分别标注(如
fn foo<'a, 'b>(x: &'a str, y: &'b str) -> &'a str)
扩展知识
- 生命周期省略规则:编译器在特定场景可自动推断生命周期(如单输入引用)
- 结构体生命周期:当结构体包含引用时也需要声明生命周期(如
struct Excerpt<'a> { part: &'a str }) - 静态生命周期:
'static表示整个程序周期(如字符串字面量)
测试用例
fn main() {
let s1 = String::from("abcd");
let s2 = "xyz";
let result = longest(s1.as_str(), s2);
println!("Longest: {}", result); // 正确输出 "abcd"
// 生命周期验证(以下代码应能编译通过)
let s3 = "hello";
let res;
{
let s4 = String::from("world");
res = longest(s3, s4.as_str());
println!("Inside: {}", res); // 正确输出 "world"
}
// println!("Outside: {}", res); // 错误!res 的生命周期已结束
}