为何Rust函数无法返回String引用却可返回切片引用?
为什么返回String的悬垂引用被禁止,但返回切片引用却合法?
核心原因很简单:你说得对,两个例子的本质区别在于引用指向的内存是谁拥有的。
先看第一个dangle函数的问题:
fn dangle() -> &String { // dangle 返回一个String的引用 let s = String::from("hello"); // s是一个新的String &s // 返回指向String s的引用 } // 此处s超出作用域并被销毁,其内存被释放。危险!
这里的String s是函数内部创建的局部变量,所有权完全属于函数自身。当函数执行完毕,s会被Rust自动销毁,对应的内存也会被回收。如果返回&s,这个引用指向的内存已经不存在了,这就是悬垂引用——Rust的借用检查器会直接拦截这种行为,避免程序访问无效内存。
再看first_word函数:
fn first_word(s: &String) -> &str { let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[0..i]; } } &s[..] }
这里的关键是:输入参数&String是一个指向外部String的引用——这个String的所有权不在first_word函数里,而是在调用这个函数的代码中。也就是说,当first_word执行完毕返回切片时,原String仍然存在(它的生命周期比函数长)。
返回的&str切片,本质是对原String某一部分的引用,它的生命周期和输入的&String是绑定的。Rust的借用检查器能确认:只要返回的切片引用还在使用,原String就一定还活着,不会出现悬垂问题。
你可能没看到的是,这个函数的完整签名其实带有生命周期标注(Rust的生命周期省略规则允许我们不用手动写出):
fn first_word<'a>(s: &'a String) -> &'a str { // ... 函数体不变 }
这里的'a表示“输入引用的生命周期”,返回的切片引用的生命周期和输入完全一致,以此保证返回的引用不会比它依赖的原数据先失效。
内容的提问来源于stack exchange,提问作者Omegon
相关产品推荐
相关产品推荐

