关于rust:为什么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?

这不是真的。 Rc是引用计数的缩写。这意味着该类型会跟踪指向所拥有数据的引用数量。这样,一旦引用计数达到0,我们就可以同时拥有多个所有者并安全地释放数据。

但是我们如何保持参考计数器有效并保持最新状态?的确,每当创建新的引用/所有者或删除引用/所有者时,我们都必须做一些事情。具体来说,在前一种情况下,我们必须增加计数器,而在后一种情况下,我们必须减少计数器。

通过实现Drop(销毁程序的Rust等效项)来减少计数器。每当变量超出范围(对于我们的目标而言是完美的)时,就会执行此drop()函数。

但是我们什么时候进行增量?您猜对了:在clone()中。根据定义,Copy特征表示可以仅通过复制以下位来复制类型:

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

在我们的情况下是不正确的,因为:是的,我们"只是复制位",但是我们还要做其他工作!我们确实需要增加我们的参考计数器!

  • DropDrop展示
  • RcClone展示


如果类型实现Drop(源),则该类型不能实现Copy。由于Rc确实实现了它以减少其引用计数,所以这是不可能的。

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

组成

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

又不仅是一个指针:

1
2
3
4
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