面试题答案
一键面试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
。这个生命周期参数被应用到了函数的参数 s1
和 s2
以及返回值上,这意味着输入的两个字符串切片 s1
和 s2
以及返回的新字符串切片都具有相同的生命周期 a
。之所以这样处理,是因为Rust的编译器需要明确知道函数返回值的生命周期与输入参数的生命周期之间的关系。在这里,返回值是由 s1
和 s2
拼接而成的,因此它的生命周期不能超过 s1
和 s2
中生命周期较短的那个,所以统一使用同一个生命周期参数 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
)还是返回拥有所有权的 String
(Cow::Owned
),从而在保证正确性的同时,尽可能提高性能。