Struct std::rc::Rc 1.0.0[−][src]
pub struct Rc<T> where
T: ?Sized, { /* fields omitted */ }
Expand description
单线程引用计数指针。Rc
代表引用计数。
有关更多详细信息,请参见 模块级文档。
Rc
的固有方法都是关联函数,这意味着您必须以例如 Rc::get_mut(&mut value)
而不是 value.get_mut()
的方式调用它们。
这样可以避免与内部类型 T
的方法发生冲突。
Implementations
使用对自身的弱引用创建一个新的 Rc<T>
。
在此函数返回之前尝试升级弱引用将得到 None
值。
但是,弱引用可以自由克隆并存储以备后用。
Examples
#![feature(arc_new_cyclic)] #![allow(dead_code)] use std::rc::{Rc, Weak}; struct Gadget { self_weak: Weak<Self>, // ... 更多领域 } impl Gadget { pub fn new() -> Rc<Self> { Rc::new_cyclic(|self_weak| { Gadget { self_weak: self_weak.clone(), /* ... */ } }) } }Run
创建一个具有未初始化内容的新 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)Run
用未初始化的内容构造一个新的 Rc
,如果分配失败,则返回错误
Examples
#![feature(allocator_api, new_uninit)] #![feature(get_mut_unchecked)] use std::rc::Rc; let mut five = Rc::<u32>::try_new_uninit()?; let five = unsafe { // 延迟初始化: Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); five.assume_init() }; assert_eq!(*five, 5);Run
创建一个具有未初始化内容的新 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);Run
创建一个新的 Pin<Rc<T>>
。
如果 T
未实现 Unpin
,则 value
将被固定在内存中并且无法移动。
创建一个新的带有未初始化内容的引用计数的切片。
Examples
#![feature(new_uninit)] #![feature(get_mut_unchecked)] use std::rc::Rc; let mut values = Rc::<[u32]>::new_uninit_slice(3); let values = unsafe { // 延迟初始化: Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); values.assume_init() }; assert_eq!(*values, [1, 2, 3])Run
用未初始化的内容创建一个新的带有引用计数的切片,内存中填充 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])Run
转换为 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(); let five = unsafe { // 延迟初始化: Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); five.assume_init() }; assert_eq!(*five, 5)Run
转换为 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 values = unsafe { // 延迟初始化: Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); values.assume_init() }; assert_eq!(*values, [1, 2, 3])Run
消耗 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");Run
从裸指针构造 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` 现在悬空了!Run
将与提供的指针关联的 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)); }Run
将与提供的指针关联的 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)); }Run
将变量引用返回给定的 Rc
,而不进行任何检查。
另请参见 get_mut
,它是安全的并且进行适当的检查。
Safety
在返回的借用期间,不得解引用其他指向相同分配的 Rc
或 Weak
指针。
如果不存在这样的指针 (例如紧接在 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
进行可变引用。
如果还有其他指向同一分配的 Rc
指针,则 make_mut
会将 clone
的内部值分配给新分配,以确保唯一的所有权。
这也称为写时克隆。
如果没有其他指向该分配的 Rc
指针,则指向该分配的 Weak
指针将被取消关联。
另请参见 get_mut
,它将失败而不是克隆。
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);Run
Weak
指针将被取消关联:
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());Run
尝试将 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));Run
Trait Implementations
获取 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