MST
星途 面试题库

面试题:Rust函数参数传递之借用与生命周期

编写一个Rust函数,该函数接受两个字符串切片作为参数,并返回一个新的字符串切片,新切片内容是两个输入切片拼接后的结果。同时要正确处理好生命周期问题,保证代码能够编译通过。请解释你是如何处理生命周期的,以及为什么要这样处理。
21.5万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
fn concatenate_strings<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    let mut result = String::with_capacity(s1.len() + s2.len());
    result.push_str(s1);
    result.push_str(s2);
    &result[..]
}

在上述代码中,<'a> 表示定义了一个生命周期参数 a。这个生命周期参数被应用到了函数的参数 s1s2 以及返回值上,这意味着输入的两个字符串切片 s1s2 以及返回的新字符串切片都具有相同的生命周期 a。之所以这样处理,是因为Rust的编译器需要明确知道函数返回值的生命周期与输入参数的生命周期之间的关系。在这里,返回值是由 s1s2 拼接而成的,因此它的生命周期不能超过 s1s2 中生命周期较短的那个,所以统一使用同一个生命周期参数 a 来标记它们的生命周期,确保编译器能够正确地进行生命周期检查并使代码编译通过。不过,这段代码实际上存在一个问题,因为 result 是在函数内部创建的局部变量,函数结束时会被销毁,返回对其的引用会导致悬垂指针。要解决这个问题,可以返回 String 类型而不是字符串切片:

fn concatenate_strings(s1: &str, s2: &str) -> String {
    let mut result = String::with_capacity(s1.len() + s2.len());
    result.push_str(s1);
    result.push_str(s2);
    result
}

如果非要返回字符串切片,可以通过 Cow 类型来动态选择返回借用的切片还是拥有所有权的 String

use std::borrow::Cow;
fn concatenate_strings<'a>(s1: &'a str, s2: &'a str) -> Cow<'a, str> {
    if s1.is_empty() {
        Cow::Borrowed(s2)
    } else if s2.is_empty() {
        Cow::Borrowed(s1)
    } else {
        let mut result = String::with_capacity(s1.len() + s2.len());
        result.push_str(s1);
        result.push_str(s2);
        Cow::Owned(result)
    }
}

这里,Cow 类型(Clone On Write 的缩写)允许根据条件动态决定是返回借用的字符串切片(Cow::Borrowed)还是返回拥有所有权的 StringCow::Owned),从而在保证正确性的同时,尽可能提高性能。