为什么 std::rc::Rc<> 不是复制?

Why is std::rc::Rc<> not Copy?

谁能给我解释一下为什么 Rc<> 不是 Copy

我正在编写使用大量共享指针的代码,不得不一直键入 .clone() 让我很紧张。

在我看来 Rc<> 应该只包含一个固定大小的指针,所以类型本身应该是 Sized,因此 Copy,对吗?

我是不是漏掉了什么?

It seems to me that Rc<> should just consist of a pointer, which is a fixed size, so the type itself should be Sized and hence Copy, right?

这不完全正确。 RcRreference Counted 的缩写。这意味着该类型会跟踪有多少引用指向拥有的数据。这样我们就可以同时拥有多个所有者并在引用计数达到 0 时安全地释放数据。


但是我们如何使参考计数器保持有效和最新?确切地说,每当创建新的 reference/owner 和删除 reference/owner 时,我们都必须做一些事情。具体来说,我们必须在前一种情况下增加计数器,在后者中减少计数器。

通过实现 Drop 来减少计数器,Rust 相当于析构函数。只要变量超出范围,就会执行此 drop() 函数 - 非常适合我们的目标。

但是我们什么时候做增量?您猜对了:在 clone() 中。 The Copy trait,根据定义,表示一个类型可以通过复制位来复制:

Types that can be copied by simply copying bits (i.e. memcpy).

在我们的案例中这不是真的,因为:是的,我们 "just copy bits",但我们还做了额外的工作!我们确实需要增加我们的参考计数器!

如果一个类型实现了 Dropsource). Since Rc does implement it 来减少它的引用计数,这是不可能的。

此外,Rc不仅仅是一个指针。它由一个 Shared:

pub struct Rc<T: ?Sized> {
    ptr: Shared<RcBox<T>>,
}

反过来,这不仅是一个指针:

pub struct Shared<T: ?Sized> {
    pointer: NonZero<*const T>,
    _marker: PhantomData<T>,
}
需要

PhantomData来表达T的所有权:

this marker has no consequences for variance, but is necessary for dropck to understand that we logically own a T.

For details, see: https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data