pub struct Rc<T: ?Sized> { /* private fields */ }
Expand description
单线程引用计数指针。Rc
代表引用计数。
有关更多详细信息,请参见 模块级文档。
Rc
的固有方法都是关联函数,这意味着您必须以例如 Rc::get_mut(&mut value)
而不是 value.get_mut()
的方式调用它们。
这样可以避免与内部类型 T
的方法发生冲突。
Implementations§
source§impl<T> Rc<T>
impl<T> Rc<T>
1.60.0 · sourcepub fn new_cyclic<F>(data_fn: F) -> Rc<T>where
F: FnOnce(&Weak<T>) -> T,
pub fn new_cyclic<F>(data_fn: F) -> Rc<T>where F: FnOnce(&Weak<T>) -> T,
创建一个新的 Rc<T>
,同时给您一个分配的 Weak<T>
,以允许您创建一个 T
,它持有一个指向自身的弱指针。
通常,直接或间接循环引用自身的结构体不应该对自身持有强引用以防止内存泄漏。
使用这个函数,您可以在 T
的初始化过程中,在 Rc<T>
创建之前访问弱指针,这样您就可以将它克隆并存储在 T
中。
new_cyclic
先给 Rc<T>
分配托管分配,然后调用您的闭包,给这个分配一个 Weak<T>
,然后再把您的闭包返回的 T
放入分配中,完成 Rc<T>
的构建。
由于新的 Rc<T>
在 Rc<T>::new_cyclic
返回之前尚未完全构造,因此在闭包内的弱引用上调用 upgrade
将失败并导致 None
值。
Panics
如果 data_fn
发生 panic,panic 会传播给调用者,而临时的 Weak<T>
会被正常丢弃。
Examples
use std::rc::{Rc, Weak};
struct Gadget {
me: Weak<Gadget>,
}
impl Gadget {
/// 创建一个引用计数的 Gadget。
fn new() -> Rc<Self> {
// `me` 是指向我们正在构建的 `Rc` 的新分配的 `Weak<Gadget>`。
Rc::new_cyclic(|me| {
// 在此处创建实际的结构体。
Gadget { me: me.clone() }
})
}
/// 返回一个指向 Self 的引用计数指针。
fn me(&self) -> Rc<Self> {
self.me.upgrade().unwrap()
}
}
Runsourcepub fn new_uninit() -> Rc<MaybeUninit<T>>
🔬This is a nightly-only experimental API. (new_uninit
#63291)
pub fn new_uninit() -> Rc<MaybeUninit<T>>
new_uninit
#63291)sourcepub fn new_zeroed() -> Rc<MaybeUninit<T>>
🔬This is a nightly-only experimental API. (new_uninit
#63291)
pub fn new_zeroed() -> Rc<MaybeUninit<T>>
new_uninit
#63291)创建一个具有未初始化内容的新 Rc
,并用 0
字节填充内存。
有关正确和不正确使用此方法的示例,请参见 MaybeUninit::zeroed
。
Examples
#![feature(new_uninit)]
use std::rc::Rc;
let zero = Rc::<u32>::new_zeroed();
let zero = unsafe { zero.assume_init() };
assert_eq!(*zero, 0)
Runsourcepub fn try_new(value: T) -> Result<Rc<T>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
#32838)
pub fn try_new(value: T) -> Result<Rc<T>, AllocError>
allocator_api
#32838)sourcepub fn try_new_uninit() -> Result<Rc<MaybeUninit<T>>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
#32838)
pub fn try_new_uninit() -> Result<Rc<MaybeUninit<T>>, AllocError>
allocator_api
#32838)sourcepub fn try_new_zeroed() -> Result<Rc<MaybeUninit<T>>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
#32838)
pub fn try_new_zeroed() -> Result<Rc<MaybeUninit<T>>, AllocError>
allocator_api
#32838)创建一个具有未初始化内容的新 Rc
,并用 0
字节填充内存,如果分配失败,则返回错误
有关正确和不正确使用此方法的示例,请参见 MaybeUninit::zeroed
。
Examples
#![feature(allocator_api, new_uninit)]
use std::rc::Rc;
let zero = Rc::<u32>::try_new_zeroed()?;
let zero = unsafe { zero.assume_init() };
assert_eq!(*zero, 0);
Run1.33.0 · sourcepub fn pin(value: T) -> Pin<Rc<T>>
pub fn pin(value: T) -> Pin<Rc<T>>
创建一个新的 Pin<Rc<T>>
。
如果 T
未实现 Unpin
,则 value
将被固定在内存中并且无法移动。
1.4.0 · sourcepub fn try_unwrap(this: Self) -> Result<T, Self>
pub fn try_unwrap(this: Self) -> Result<T, Self>
1.70.0 · sourcepub fn into_inner(this: Self) -> Option<T>
pub fn into_inner(this: Self) -> Option<T>
source§impl<T> Rc<[T]>
impl<T> Rc<[T]>
sourcepub fn new_uninit_slice(len: usize) -> Rc<[MaybeUninit<T>]>
🔬This is a nightly-only experimental API. (new_uninit
#63291)
pub fn new_uninit_slice(len: usize) -> Rc<[MaybeUninit<T>]>
new_uninit
#63291)创建一个新的带有未初始化内容的引用计数的切片。
Examples
#![feature(new_uninit)]
#![feature(get_mut_unchecked)]
use std::rc::Rc;
let mut values = Rc::<[u32]>::new_uninit_slice(3);
// 延迟初始化:
let data = Rc::get_mut(&mut values).unwrap();
data[0].write(1);
data[1].write(2);
data[2].write(3);
let values = unsafe { values.assume_init() };
assert_eq!(*values, [1, 2, 3])
Runsourcepub fn new_zeroed_slice(len: usize) -> Rc<[MaybeUninit<T>]>
🔬This is a nightly-only experimental API. (new_uninit
#63291)
pub fn new_zeroed_slice(len: usize) -> Rc<[MaybeUninit<T>]>
new_uninit
#63291)用未初始化的内容创建一个新的带有引用计数的切片,内存中填充 0
字节。
有关正确和不正确使用此方法的示例,请参见 MaybeUninit::zeroed
。
Examples
#![feature(new_uninit)]
use std::rc::Rc;
let values = Rc::<[u32]>::new_zeroed_slice(3);
let values = unsafe { values.assume_init() };
assert_eq!(*values, [0, 0, 0])
Runsource§impl<T> Rc<MaybeUninit<T>>
impl<T> Rc<MaybeUninit<T>>
sourcepub unsafe fn assume_init(self) -> Rc<T>
🔬This is a nightly-only experimental API. (new_uninit
#63291)
pub unsafe fn assume_init(self) -> Rc<T>
new_uninit
#63291)转换为 Rc<T>
。
Safety
与 MaybeUninit::assume_init
一样,由调用者负责确保内部值确实处于初始化状态。
在内容尚未完全初始化时调用此方法会立即导致未定义的行为。
Examples
#![feature(new_uninit)]
#![feature(get_mut_unchecked)]
use std::rc::Rc;
let mut five = Rc::<u32>::new_uninit();
// 延迟初始化:
Rc::get_mut(&mut five).unwrap().write(5);
let five = unsafe { five.assume_init() };
assert_eq!(*five, 5)
Runsource§impl<T> Rc<[MaybeUninit<T>]>
impl<T> Rc<[MaybeUninit<T>]>
sourcepub unsafe fn assume_init(self) -> Rc<[T]>
🔬This is a nightly-only experimental API. (new_uninit
#63291)
pub unsafe fn assume_init(self) -> Rc<[T]>
new_uninit
#63291)转换为 Rc<[T]>
。
Safety
与 MaybeUninit::assume_init
一样,由调用者负责确保内部值确实处于初始化状态。
在内容尚未完全初始化时调用此方法会立即导致未定义的行为。
Examples
#![feature(new_uninit)]
#![feature(get_mut_unchecked)]
use std::rc::Rc;
let mut values = Rc::<[u32]>::new_uninit_slice(3);
// 延迟初始化:
let data = Rc::get_mut(&mut values).unwrap();
data[0].write(1);
data[1].write(2);
data[2].write(3);
let values = unsafe { values.assume_init() };
assert_eq!(*values, [1, 2, 3])
Runsource§impl<T: ?Sized> Rc<T>
impl<T: ?Sized> Rc<T>
1.17.0 · sourcepub fn into_raw(this: Self) -> *const T
pub fn into_raw(this: Self) -> *const T
消耗 Rc
,返回包装的指针。
为避免内存泄漏,必须使用 Rc::from_raw
将指针转换回 Rc
。
Examples
use std::rc::Rc;
let x = Rc::new("hello".to_owned());
let x_ptr = Rc::into_raw(x);
assert_eq!(unsafe { &*x_ptr }, "hello");
Run1.17.0 · sourcepub unsafe fn from_raw(ptr: *const T) -> Self
pub unsafe fn from_raw(ptr: *const T) -> Self
从裸指针构造 Rc<T>
。
裸指针必须事先由调用返回到 Rc<U>::into_raw
,其中 U
的大小和对齐方式必须与 T
相同。
如果 U
是 T
,这是很简单的。
请注意,如果 U
不是 T
,但是具有相同的大小和对齐方式,则基本上就像对不同类型的引用进行转换一样。
有关在这种情况下适用哪些限制的更多信息,请参见 mem::transmute
。
from_raw
的用户必须确保 T
的特定值仅被丢弃一次。
此函数不安全,因为使用不当可能会导致内存不安全,即使从未访问返回的 Rc<T>
也是如此。
Examples
use std::rc::Rc;
let x = Rc::new("hello".to_owned());
let x_ptr = Rc::into_raw(x);
unsafe {
// 转换回 `Rc` 以防止泄漏。
let x = Rc::from_raw(x_ptr);
assert_eq!(&*x, "hello");
// 进一步调用 `Rc::from_raw(x_ptr)` 将导致内存不安全。
}
// 当 `x` 超出上面的作用域时,其内存将被释放,所以 `x_ptr` 现在悬垂了!
Run1.15.0 · sourcepub fn weak_count(this: &Self) -> usize
pub fn weak_count(this: &Self) -> usize
1.15.0 · sourcepub fn strong_count(this: &Self) -> usize
pub fn strong_count(this: &Self) -> usize
1.53.0 · sourcepub unsafe fn increment_strong_count(ptr: *const T)
pub unsafe fn increment_strong_count(ptr: *const T)
将与提供的指针关联的 Rc<T>
上的强引用计数增加 1。
Safety
指针必须是通过 Rc::into_raw
获得的,并且关联的 Rc
实例必须是有效的 (即
在此方法的持续时间内,强引用计数必须至少为 1)。
Examples
use std::rc::Rc;
let five = Rc::new(5);
unsafe {
let ptr = Rc::into_raw(five);
Rc::increment_strong_count(ptr);
let five = Rc::from_raw(ptr);
assert_eq!(2, Rc::strong_count(&five));
}
Run1.53.0 · sourcepub unsafe fn decrement_strong_count(ptr: *const T)
pub unsafe fn decrement_strong_count(ptr: *const T)
将与提供的指针关联的 Rc<T>
上的强引用计数减一。
Safety
指针必须是通过 Rc::into_raw
获得的,并且关联的 Rc
实例必须是有效的 (即
调用此方法时,强引用计数必须至少为 1)。
此方法可用于释放最终的 Rc
和后备存储,但不应在最终的 Rc
释放后调用。
Examples
use std::rc::Rc;
let five = Rc::new(5);
unsafe {
let ptr = Rc::into_raw(five);
Rc::increment_strong_count(ptr);
let five = Rc::from_raw(ptr);
assert_eq!(2, Rc::strong_count(&five));
Rc::decrement_strong_count(ptr);
assert_eq!(1, Rc::strong_count(&five));
}
Runsourcepub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T
🔬This is a nightly-only experimental API. (get_mut_unchecked
#63292)
pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T
get_mut_unchecked
#63292)将变量引用返回给定的 Rc
,而不进行任何检查。
另请参见 get_mut
,它是安全的并且进行适当的检查。
Safety
如果存在指向同一分配的任何其他 Rc
或 Weak
指针,则在返回的借用期间,它们不得被解引用或具有活动借用,并且它们的内部类型必须与此 Rc 的内部类型完全相同 (包括生命周)。
如果不存在这样的指针 (例如紧接在 Rc::new
之后),则情况很简单。
Examples
#![feature(get_mut_unchecked)]
use std::rc::Rc;
let mut x = Rc::new(String::new());
unsafe {
Rc::get_mut_unchecked(&mut x).push_str("foo")
}
assert_eq!(*x, "foo");
Run指向同一分配的其他 Rc
指针必须指向同一类型。
#![feature(get_mut_unchecked)]
use std::rc::Rc;
let x: Rc<str> = Rc::from("Hello, world!");
let mut y: Rc<[u8]> = x.clone().into();
unsafe {
// 这是未定义的行为,因为 x 的内部类型是 str,而不是 [u8]
Rc::get_mut_unchecked(&mut y).fill(0xff); // 0xff 在 UTF-8 中无效
}
println!("{}", &*x); // str 中的 UTF-8 无效
Run指向同一分配的其他 Rc
指针必须指向完全相同的类型,包括生命周期。
#![feature(get_mut_unchecked)]
use std::rc::Rc;
let x: Rc<&str> = Rc::new("Hello, world!");
{
let s = String::from("Oh, no!");
let mut y: Rc<&str> = x.clone().into();
unsafe {
// 这是未定义的行为,因为 x 的内部类型是 &'long str,而不是 &'short str
*Rc::get_mut_unchecked(&mut y) = &s;
}
}
println!("{}", &*x); // Use-after-free
Run1.17.0 · sourcepub fn ptr_eq(this: &Self, other: &Self) -> bool
pub fn ptr_eq(this: &Self, other: &Self) -> bool
如果两个 Rc
以类似于 ptr::eq
的方式指向相同的分配,则返回 true
。
比较 dyn Trait
指针时的注意事项,请参见 that function。
Examples
use std::rc::Rc;
let five = Rc::new(5);
let same_five = Rc::clone(&five);
let other_five = Rc::new(5);
assert!(Rc::ptr_eq(&five, &same_five));
assert!(!Rc::ptr_eq(&five, &other_five));
Runsource§impl<T: Clone> Rc<T>
impl<T: Clone> Rc<T>
1.4.0 · sourcepub fn make_mut(this: &mut Self) -> &mut T
pub fn make_mut(this: &mut Self) -> &mut T
对给定的 Rc
进行可变引用。
如果还有其他指向同一分配的 Rc
指针,则 make_mut
会将 clone
的内部值分配给新分配,以确保唯一的所有权。
这也称为写时克隆。
但是,如果没有其他指向此分配的 Rc
指针,而是一些 Weak
指针,则 Weak
指针将被解除关联,并且不会克隆内部值。
另请参见 get_mut
,它将失败而不是克隆内部值或解除 Weak
指针的关联。
Examples
use std::rc::Rc;
let mut data = Rc::new(5);
*Rc::make_mut(&mut data) += 1; // 不会克隆任何东西
let mut other_data = Rc::clone(&data); // 不会克隆内部数据
*Rc::make_mut(&mut data) += 1; // 克隆内部数据
*Rc::make_mut(&mut data) += 1; // 不会克隆任何东西
*Rc::make_mut(&mut other_data) *= 2; // 不会克隆任何东西
// 现在,`data` 和 `other_data` 指向不同的分配。
assert_eq!(*data, 8);
assert_eq!(*other_data, 12);
RunWeak
指针将被解除关联:
use std::rc::Rc;
let mut data = Rc::new(75);
let weak = Rc::downgrade(&data);
assert!(75 == *data);
assert!(75 == *weak.upgrade().unwrap());
*Rc::make_mut(&mut data) += 1;
assert!(76 == *data);
assert!(weak.upgrade().is_none());
Runsourcepub fn unwrap_or_clone(this: Self) -> T
🔬This is a nightly-only experimental API. (arc_unwrap_or_clone
#93610)
pub fn unwrap_or_clone(this: Self) -> T
arc_unwrap_or_clone
#93610)如果我们有 T
的唯一引用,那就打开它。否则,克隆 T
并返回克隆。
假设 rc_t
是 Rc<T>
类型,这个函数在功能上等同于 (*rc_t).clone()
,但会尽可能避免克隆内部值。
Examples
#![feature(arc_unwrap_or_clone)]
let inner = String::from("test");
let ptr = inner.as_ptr();
let rc = Rc::new(inner);
let inner = Rc::unwrap_or_clone(rc);
// 内部值没有被克隆
assert!(ptr::eq(ptr, inner.as_ptr()));
let rc = Rc::new(inner);
let rc2 = rc.clone();
let inner = Rc::unwrap_or_clone(rc);
// 因为有两个引用,我们不得不克隆内部值。
assert!(!ptr::eq(ptr, inner.as_ptr()));
// `rc2` 是最后一个引用,所以当我们打开它时,我们会得到原来的 `String`。
let inner = Rc::unwrap_or_clone(rc2);
assert!(ptr::eq(ptr, inner.as_ptr()));
Runsource§impl Rc<dyn Any>
impl Rc<dyn Any>
1.29.0 · sourcepub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>>
pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>>
尝试将 Rc<dyn Any>
转换为具体类型。
Examples
use std::any::Any;
use std::rc::Rc;
fn print_if_string(value: Rc<dyn Any>) {
if let Ok(string) = value.downcast::<String>() {
println!("String ({}): {}", string.len(), string);
}
}
let my_string = "Hello World".to_string();
print_if_string(Rc::new(my_string));
print_if_string(Rc::new(0i8));
Runsourcepub unsafe fn downcast_unchecked<T: Any>(self) -> Rc<T>
🔬This is a nightly-only experimental API. (downcast_unchecked
#90850)
pub unsafe fn downcast_unchecked<T: Any>(self) -> Rc<T>
downcast_unchecked
#90850)Trait Implementations§
1.45.0 · source§impl<'a, B> From<Cow<'a, B>> for Rc<B>where
B: ToOwned + ?Sized,
Rc<B>: From<&'a B> + From<B::Owned>,
impl<'a, B> From<Cow<'a, B>> for Rc<B>where B: ToOwned + ?Sized, Rc<B>: From<&'a B> + From<B::Owned>,
1.37.0 · source§impl<T> FromIterator<T> for Rc<[T]>
impl<T> FromIterator<T> for Rc<[T]>
source§fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
获取 Iterator
中的每个元素,并将其收集到 Rc<[T]>
中。
性能特点
一般情况
在一般情况下,首先要收集到 Vec<T>
中来收集到 Rc<[T]>
中。也就是说,编写以下内容时:
let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect();
Run这就像我们写的那样:
let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0)
.collect::<Vec<_>>() // 第一组分配在此处发生。
.into(); // `Rc<[T]>` 的第二个分配在此处进行。
Run这将分配构造 Vec<T>
所需的次数,然后分配一次,以将 Vec<T>
转换为 Rc<[T]>
。
已知长度的迭代器
当您的 Iterator
实现 TrustedLen
且大小正确时,将为 Rc<[T]>
进行一次分配。例如:
let evens: Rc<[u8]> = (0..10).collect(); // 这里只进行一次分配。
Run