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
指针,则 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());
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));
RunTrait 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