std::rc::Weak<T>
有以下定义:
pub struct Weak<T: ?Sized> {
ptr: NonNull<RcBox<T>>,
}
在我的理解中,当没有更多的
Rc<T>
剩余时,RcBox<T>
将被释放并且Weak<T>.ptr
现在指向一个可能包含任何东西的地方。那么当在 upgrade()
上调用 Weak<T>
时,它怎么知道指针现在无效了?
Weak<T>::upgrade
有以下实现:
pub fn upgrade(&self) -> Option<Rc<T>> {
let inner = self.inner()?;
if inner.strong() == 0 {
None
} else {
unsafe {
inner.inc_strong();
Some(Rc::from_inner(self.ptr))
}
}
}
这是否意味着当没有
RcBox<T>
留在野外时Rc<T>
并没有真正被释放?如果是这样,那不会泄漏内存吗?
RcBox
不会被销毁,直到没有强指针或弱指针剩余。
但是,当强计数达到零时,所包含的
T
会掉落到位。这有效地破坏了包含的T
,但不会释放T
本身的记忆。
一旦弱计数也达到零,
RcBox
本身就会被释放。所以不,没有内存泄漏。
请注意,许多类型(例如
String
和 Vec
)管理单独的堆分配。如果你有一个 Rc<Vec<_>>
,例如,当强计数达到零但弱计数没有时,内部 Vec
的删除代码运行并删除它拥有的所有元素,并释放用于堆分配的堆分配存储它们。 Vec
本身用于保存堆指针、长度和容量的内存是 not 释放的,因为它由 RcBox
拥有。只有当强计数和弱计数都为零时,才会释放该分配。