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

Rust链式调用收集Vec<&Post>报错E0716的原因解析

Rust临时值被释放错误(E0716):链式调用vs分步调用的差异解析

刚学习Rust,尝试从模拟API获取并反序列化Post结构体的Vec,分两步编写代码可正常运行,但将操作链式整合后出现E0716错误(临时值被释放仍被借用),无法理解两种写法的差异及错误原因。

正常运行的代码

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Post {
    user_id: i32,
    id: i32,
    title: String,
    body: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let posts = reqwest::get("https://jsonplaceholder.typicode.com/posts")
        .await?
        .json::<Vec<Post>>()
        .await?;

    let posts = posts
        .iter()
        .map(|post| post)
        .collect::<Vec<&Post>>();

    println!("{:#?}", posts);

    Ok(())
}

报错的链式调用代码

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let posts = reqwest::get("https://jsonplaceholder.typicode.com/posts")
        .await?
        .json::<Vec<Post>>()
        .await?
        .iter()
        .map(|post| post)
        .collect::<Vec<&Post>>();

    println!("{:#?}", posts);

    Ok(())
}

错误信息

error[E0716]: temporary value dropped while borrowed
  --> src/lib.rs:15:17
   |
15 |       let posts = reqwest::get("https://jsonplaceholder.typicode.com/posts")
   |  _________________^
16 | |         .await?
17 | |         .json::<Vec<Post>>()
18 | |         .await?
   | |_______________^ creates a temporary value which is freed while still in use
...
21 |           .collect::<Vec<&Post>>();
   |                                   - temporary value is freed at the end of this statement
...
24 |       println!("{:#?}", posts);
   |                         ----- borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value

原因解析

核心差异:临时值的生命周期

两种写法的本质区别在于拥有所有权的Vec<Post>的生命周期:

  1. 分步写法:

    • 第一行let posts = ...将反序列化得到的Vec<Post>绑定到了变量posts上,这个变量的生命周期贯穿整个main函数剩余部分。
    • 后续调用posts.iter()生成的引用,生命周期和posts完全一致。收集成Vec<&Post>后,这些引用指向的原Vec<Post>依然存活,所以引用始终有效。
  2. 链式写法:

    • .json::<Vec<Post>>().await?返回的Vec<Post>是一个临时值,没有被绑定到任何变量。Rust中临时值的生命周期仅局限于当前语句(即到末尾的;为止)。
    • 你通过iter()获取了这个临时Vec<Post>的引用,并收集成Vec<&Post>。当语句结束,临时Vec<Post>会被立即销毁,导致posts中的所有引用都变成了悬空引用——指向已经被释放的内存,因此编译器抛出E0716错误。

解决思路

  • 最直接的方式就是像分步写法那样,先将拥有所有权的Vec<Post>绑定到变量,确保其生命周期覆盖引用的使用范围。
  • 如果不需要引用,也可以直接使用原Vec<Post>,或者通过clone()生成新的Vec<Post>(而非引用集合),避免依赖临时值的生命周期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 07:07:38