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

Rust临时值为何有时可引用有时不可?核心场景疑问

Rust临时值生命周期的核心规则解析

一、两段i32代码的差异本质

可运行代码:

fn main() {
    let a = &get_i32();
    println!("{}", a);
}
fn get_i32() -> i32 {
    return 100;
}

报错代码:

fn main() {
    let a;
    a = &get_i32();
    println!("{}", a);
}

编译器错误输出:

error[E0716]: temporary value dropped while borrowed
 --> src/bin/rust_course.rs:8:10
  |
8 |     a = &get_i32();
  |          ^^^^^^^^^- temporary value is freed at the end of this statement
  |          |
  |          creates a temporary value which is freed while still in use
9 |     println!("{}", a);
  |                    - borrow later used here
  |
help: consider using a `let` binding to create a longer lived value
  |
8 ~     let binding = get_i32();
9 ~     a = &binding;
  |

For more information about this error, try `rustc --explain E0716`.

差异核心是Rust的临时值生命周期延长规则:当使用let 变量 = &临时值的直接绑定形式时,编译器会自动将临时值的生命周期延长至与该变量一致。第一段代码中,get_i32()返回的临时i32值,生命周期被延长到和a相同,直到main函数结束才销毁,因此a的引用始终有效。

而第二段代码是先声明a再赋值,此时&get_i32()产生的临时值仅存活到当前语句结束(即a = &get_i32();执行完成),之后临时值被销毁,a变为悬空引用,触发E0716错误。

二、s1与s2的写法差异

代码示例:

fn main() {
    let s1 = &String::from("hello world");
    println!("{}", s1);
    let s2 = String::from("hello world").as_str();
    println!("{}", s2);
}

编译器错误输出:

error[E0716]: temporary value dropped while borrowed
 --> src/bin/rust_course.rs:6:14
  |
6 |     let s2 = String::from("hello world").as_str();
  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^         - temporary value is freed at the end of this statement
  |              |
  |              creates a temporary value which is freed while still in use
7 |     println!("{}", s2);
  |                    -- borrow later used here
  |
help: consider using a `let` binding to create a longer lived value
  |
6 ~     let binding = String::from("hello world");
7 ~     let s2 = binding.as_str();
  |

For more information about this error, try `rustc --explain E0716`.
  • s1的写法是&String::from(...),符合直接绑定引用到变量的规则,临时String的生命周期被延长至与s1一致,直到main函数结束,因此s1的引用有效。
  • s2的写法是链式调用:String::from(...).as_str(),这种场景不触发生命周期延长——延长规则仅适用于let 变量 = &临时值的直接绑定形式,链式调用产生的临时值会在当前语句结束后立即销毁,导致s2变为悬空引用,触发错误。

三、传函数与赋值给变量的差异

可运行代码:

fn main() {
    print(String::from("hello world").as_str());
}

fn print(str: &str) {
    println!("{}", str);
}

这里的规则是:当临时值被用作函数参数时,它的生命周期会被延长到整个函数调用的持续时间。也就是说,在print(...)函数执行期间,临时String会一直存在,as_str()返回的引用在函数内部完全有效;函数执行完毕后,临时值才被销毁,此时引用已不再被使用,因此不会触发错误。

而赋值给变量时,变量的生命周期会超过当前语句(比如后续还有println!使用该变量),但临时值在语句结束就销毁,导致引用悬空,这就是两者的本质区别。


内容的提问来源于stack exchange,提问作者artzok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:13:20