Rust 智能指针(二)

1. Rc<T> 引用计数指针

Rc<T> 是引用计数指针,可以使用clone使得指针所指向的数据具有多个所有者。

enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use List::{Cons, Nil};
use std::rc::Rc;

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    let b = Cons(3, Rc::clone(&a));
    let c = Cons(4, Rc::clone(&a));
}

需要注意的是,Rc<T>指针的数据是不可变的

2. RefCell<T> 内部可变指针

RefCell<T>指针可以绕过编译期借用检查,普通指针和引用同一时间只能有一个可变引用或者多个不可变引用。而RefCell<T>把这个检查推迟到了运行时。如果有引用违反了借用原则,程序会panic!

use std::cell::RefCell;

struct S{
    data:i32
}
fn main() {
    let s = RefCell::new(S{data:3});
    s.borrow_mut().data=5;
    println!("{}",s.borrow().data);
}

通过&self.borrow()获得一个不可变借用,&self.borrrow_mut()获得一个可变借用。

use std::cell::RefCell;

struct S{
    data:i32
}
fn main() {
    let s = RefCell::new(S{data:3});
    let s1=s.borrow_mut();
    let s2 = s.borrow_mut();
}

s有两个可变引用,这很明显违反了引用借用原则。所以运行后会得到一个panic。

thread 'main' panicked at 'already borrowed: BorrowMutError', src\libcore\result.rs:997:5
stack backtrace:
   0: std::sys_common::backtrace::_print
             at src\libstd\sys\windows\backtrace/mod.rs:95
             at src\libstd\sys\windows\backtrace/mod.rs:82
             at src\libstd\sys_common/backtrace.rs:71
   1: std::panicking::default_hook::{{closure}}
             at src\libstd\sys_common/backtrace.rs:59
             at src\libstd/panicking.rs:197
   2: std::panicking::default_hook
             at src\libstd/panicking.rs:211
   3: std::panicking::rust_panic_with_hook
             at src\libstd/panicking.rs:474
   4: std::panicking::continue_panic_fmt
             at src\libstd/panicking.rs:381
   5: rust_begin_unwind
             at src\libstd/panicking.rs:308
   6: core::panicking::panic_fmt
             at src\libcore/panicking.rs:85
   7: core::result::unwrap_failed
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libcore/macros.rs:18
   8: core::result::Result<T,E>::expect
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libcore/result.rs:825
   9: core::cell::RefCell<T>::borrow_mut
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libcore/cell.rs:873
  10: untitled::main
             at src/main.rs:9
  11: std::rt::lang_start::{{closure}}
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libstd/rt.rs:64
  12: std::panicking::try::do_call
             at src\libstd/rt.rs:49
             at src\libstd/panicking.rs:293
  13: _rust_maybe_catch_panic
             at src\libpanic_unwind/lib.rs:87
  14: std::rt::lang_start_internal
             at src\libstd/panicking.rs:272
             at src\libstd/panic.rs:388
             at src\libstd/rt.rs:48
  15: std::rt::lang_start
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libstd/rt.rs:64
  16: main
  17: _tmainCRTStartup
  18: mainCRTStartup
  19: unit_addrs_search
  20: unit_addrs_search

3.使用Rc<T>和RefCell<T>构建具有多个所有者的可变引用

use std::cell::RefCell;
use std::rc::Rc;


struct S{
    data:i32
}
fn main() {
    let s = Rc::new( RefCell::new(S{data:3}));
    let s1 = Rc::clone(&s);
    s1.borrow_mut().data=43;
    println!("{}",RefCell::borrow(&s).data);
}

输出43

posted @ 2019-06-29 14:35  雨雾星天  阅读(670)  评论(0编辑  收藏  举报