36

Rc 类型总结

 5 years ago
source link: https://PrivateRookie.github.io/2019-05-12-rust-rc/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ref: alloc::rc::Rc - Rust

std::rc::Rc单线程 引用计数指针。’RC’ 代表 ‘Reference Counted’。 翻阅 module-level-documentation 查看更多信息 Rc 的固有方法都是关联函数,这意味在使用应该是用类似 Rc::get_mut(&mut value) 而不是 value.get_mut() 的方式调用。这可以避免与其包含的类型方法冲突。

方法

new

pub fn new(value: T) -> Rc<T>

构造一个 Rc<T>

例子

use std::rc::Rc;

let five = Rc::new(5);

pin

pub fn pin(value: T) -> Pin<Rc<T>>

构建一个新的 Pin<Rc<T>> 。如果 T 没有实现 Unpin,那么 value 将会固定在内存中不可移动。

try_unwrap

pub fn try_unwrap(this: Self) -> Result<T, Self>

如果 Rc 有且只有1个强引用,则返回包含的值,否则返回 Err<T> 。 不管 Rc 有多少弱引用,只要符合上述条件,该函数都将成功。

use std::rc::Rc;

fn main() {
    let x = Rc::new(3);
    assert_eq!(Rc::try_unwrap(x), Ok(3));

    let x = Rc::new(4);
    let _y = Rc::clone(&x); // 调用 clone 增强强引用
    assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4); // Rc::try_unwrap(x) 返回 Err(4)
}

into_raw

pub fn into_raw(this: Self) -> *const T

消费 Rc, 返回被包装的指针。 为了避免内存泄漏,被包装的指针如果要被重新转换为 Rc, 应该使用 Rc::from_raw

例子

use std::rc::Rc;

fn main() {
    let x = Rc::new(4);
    let x_ptr = Rc::into_raw(x); // x_ptr 为裸指针 0x142fdcde020
    assert_eq!(unsafe { *x_ptr }, 4);
}

from_raw

pub unsafe fn from_raw(ptr: *const T) -> Self

从裸指针中构建一个 Rc。 裸指针必须是从 Rc::into_raw 中返回的裸指针。 这个函数是不安全的,因为不正确使用可能会导致内存问题。例如,在裸指针上二次释放资源。

use std::rc::Rc;

let x = Rc::new(10);
let x_ptr = Rc::into_raw(x);

unsafe {
    // 转换成 Rc 避免内存泄漏
    let x = Rc::from_raw(x_ptr);
    assert_eq!(*x, 10);

    // 再次调用 `Rc::from_row(x_ptr)` 会导致内存不安全
}

// `x` 的内存将会在离开作用域后释放,所以 `x_ptr` 不是悬吊指针

downgrade

pub fn downgrade(this: &Self) -> Weak<T>

创建一个被包裹值的弱引用指针

例子

use std::rc::Rc;

let five = Rc::new(5);

let weak_five = Rc::downgrade(&five);

weak_count

返回弱引用计数

例子

use std::rc::Rc;

let five = Rc::new(5);
let _weak_five = Rc::downgrade(&five);

assert_eq!(1, Rc::weak_cont(&five));

strong_count

返回强引用计数

例子

use std::rc::Rc;

let five = Rc::new(5);
let _also_five = Rc::clone(&five);

assert_eq!(2, Rc::strong_count(&five));

get_mut

如果没有其他 Rc 或者 Weak 指针指向内部值,则返回内部值的可变引用,否则返回 None,因为改变共享值是不安全的。 另见 make_mut ,这方法会在内部值处于共享状态时克隆内部值。

例子

use std::rc::Rc;

let mut x = Rc::new(3);
*Rc::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);

let _y = Rc::clone(&x);
assert!(Rc::get_mut(&mut x).is_none());

ptr_eq

判断两个指针是否指向同一个值

例子

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_file));
assert!(!Rc::ptr_eq(&five, &other_file));

make_mut

pub fn make_mut(this: &mut Self) -> &mut T

创建一个 Rc 的可变引用。如果 Rc 还有其他引用或弱引用, make_mut 将会克隆内部值以保证所有权的唯一性。这也被称为写时克隆。

另见 get_mut ,这个方法会失败而不是克隆

例子

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);

downcast

pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>>

尝试将 Rc 降级为具体值

例子

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);
    }
}

fn main() {
    let my_string = "Hello World".to_string();
    print_if_string(Rc::new(my_string));
    print_if_string(Rc::new(0i8)); // 不会打印
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK