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

Rust疑问:为何借用结构体内部引用会导致整个结构体被借用?

问题分析与解答

首先看你的代码:

struct MyStruct<'a>{
    data: &'a str,
}

fn get<'a>(S: &'a MyStruct<'a>) -> &'a str{
    S.data
}

fn set<'a>(S: &'a mut MyStruct<'a>, x: &'a str){
    S.data = x;
}

fn main(){
    let mut S = MyStruct{data: "hello"};
    let foo: &str = get(&S);
    set(&mut S, "goodbye");
    dbg!(foo);
}

为什么原代码编译失败?

你原get函数的生命周期注解把结构体的引用生命周期和结构体内部data的生命周期绑定成了同一个'a。这相当于告诉Rust:返回的&str的存活时间,和你传入的结构体引用的存活时间完全一致。

所以在main里,let foo = get(&S)这行,Rust会认为:只要foo还活着(一直到dbg!(foo)),S的不可变借用就不能被释放。而下一行set(&mut S)需要获取S的可变借用,Rust的借用规则禁止同时存在可变和不可变借用,自然就编译报错了。

修改签名后为什么能编译?

当你把get改成fn get<'a, 'b>(S: &'a MyStruct<'b>) -> &'b str时,相当于把两个生命周期解耦了:

  • 'a是结构体引用的生命周期:这个生命周期只覆盖get函数调用的那段时间,函数执行完,结构体的不可变借用就释放了。
  • 'b是内部data的生命周期:这里data是字符串字面量,生命周期是'static,所以返回的foo可以一直活到main结束。

这样一来,get调用结束后,S的不可变借用就失效了,后面调用set获取可变借用就不会和foo的存活产生冲突,编译自然通过。

另外提一句,你原set函数的签名也有类似的生命周期绑定问题,但这次编译失败的核心原因在get的生命周期绑定逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:50:28