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
相关产品推荐
相关产品推荐

