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

Rust如何创建含非循环引用的结构体向量?是否需用Rc/Weak?

Rust中结构体引用Vector内实例的问题

需求说明

想要创建一个TestStruct类型的vector,TestStruct包含一个指向另一个TestStruct实例的可选引用。预期场景中不会出现自引用或循环引用,多个实例可引用同一个TestStruct,且实例无需可变。

当前代码及错误

代码:

struct TestStruct<'a>
{
    other: Option<&'a TestStruct<'a>>
}

fn testFn()
{
    let mut events = vec![TestStruct{other: None}];
    events.push(TestStruct{other: Some(&events[0])});
}

编译错误:

error[E0502]: cannot borrow `events` as mutable because it is also borrowed as immutable
 --> src\test.rs:9:5
  |
9 |     events.push(TestStruct{other: Some(&events[0])});
  |     ^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^------^^^^^^
  |     |      |                            |
  |     |      |                            immutable borrow occurs here
  |     |      immutable borrow later used by call
  |     mutable borrow occurs here

问题解答

1. 能否仅用引用实现需求?

不行。核心原因有两点:

  • 借用规则冲突:调用events.push需要对vector做可变借用,但创建&events[0]时又产生了不可变借用,Rust的借用检查器不允许同一时间存在可变和不可变借用。
  • 悬垂引用风险:即使调整代码顺序,vector在扩容时会重新分配内存并移动内部元素,之前获取的元素引用会变成悬垂引用,这是Rust严格禁止的。

普通引用的生命周期绑定到vector的可变状态上,无法适配这种动态添加元素并引用已有元素的场景。

2. 改用Box<TestStruct>的vector能否解决问题?

不能。引用Box<TestStruct>内部的实例时,依然需要先对vector做不可变借用(&events[0]),调用push时的可变借用依然会和这个不可变借用冲突,编译错误无法解决。

虽然Box把结构体放在堆上,vector扩容时Box本身的移动不会改变堆中结构体的地址,但借用检查器只关心vector本身的借用状态,不会考虑堆内存的稳定性,所以依然过不了编译。

3. 推荐方案:使用Rc

你的场景是共享不可变实例,且无循环引用,完全适合用Rc(引用计数智能指针)来实现。Rc允许多个所有者共享同一个不可变数据,clone操作只是增加引用计数,不会复制数据。

修改后的代码:

use std::rc::Rc;

struct TestStruct {
    other: Option<Rc<TestStruct>>,
}

fn testFn() {
    let mut events = vec![Rc::new(TestStruct { other: None })];
    events.push(Rc::new(TestStruct { other: Some(Rc::clone(&events[0])) }));
}

这段代码可以正常编译,完美满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:15:54