为什么我可以对 Rc 使用动态调度,但不能对 RefCell 使用?

Pap*_*ika 0 rust

Rc用于对实现特征的对象进行动态调度。然后我需要内部可变性,所以我改为RefCell. 我认为这RefCell只是Rc内部可变性的一个,但它不会接受我的 trait 对象。

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

trait Test {}

struct A;

impl Test for A {}

fn main() {
    // This works:
    let x: Rc<dyn Test> = Rc::new(A);
    
    // But this not:
    // let x: RefCell<dyn Test> = RefCell::new(A);
}
Run Code Online (Sandbox Code Playgroud)

错误:

error[E0308]: mismatched types
  --> src/main.rs:18:32
   |
18 |     let x: RefCell<dyn Test> = RefCell::new(A);
   |            -----------------   ^^^^^^^^^^^^^^^ expected trait object `dyn Test`, found struct `A`
   |            |
   |            expected due to this
   |
   = note: expected struct `std::cell::RefCell<dyn Test>`
              found struct `std::cell::RefCell<A>`

error[E0277]: the size for values of type `dyn Test` cannot be known at compilation time
  --> src/main.rs:18:9
   |
18 |     let x: RefCell<dyn Test> = RefCell::new(A);
   |         ^ doesn't have a size known at compile-time
   |
   = help: within `std::cell::RefCell<dyn Test>`, the trait `std::marker::Sized` is not implemented for `dyn Test`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required because it appears within the type `std::cell::RefCell<dyn Test>`
   = note: all local variables must have a statically known size
   = help: unsized locals are gated as an unstable feature
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 9

ARefCell是促进内部可变性的包装结构,而 anRc是引用计数智能指针。它们完全不同并且用于正交目的。如果要使用具有内部可变性的特征对象,可以将Rc和组合RefCellRc<RefCell<dyn Test>>

ARefCell提供了一种在运行时借用包装值的安全机制。Rust 对引用的要求——可变借用是独占的——在你使用borrow()orborrow_mut()方法时根据存储在RefCell包装值旁边的标志进行检查。

AnRc是引用计数的智能指针。它允许多个所有者拥有一个堆分配的值。一旦所有引用都被删除,指针将被释放。如您所见,此功能与在运行时检查借用无关。

如果您将动态大小的类型(如 trait 对象)包装在 a 中RefCell,您最终会得到一个动态大小的RefCell. 在 Rust 中,动态大小的类型不能存储在堆栈中,因此您必须将它放在某种引用之后。在这种情况下Rc似乎最合适,因为 aRefCell与共享所有权结合使用时最有用。

相关问题:

本书的这一部分提供了进一步的解释: