You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 04:18:14