我认为我已经理解了Rust中的胖指针,但我无法理解为什么它们似乎从内部类型向外渗透。大概我的心理模型是关闭的,但我正在努力为这段代码找到一个令人满意的解释:
use std::cell::RefCell;
use std::fmt::Debug;
use std::mem::size_of;
use std::rc::Rc;
fn main() {
println!("{}", size_of::<Rc<RefCell<Vec<u8>>>>());
println!("{}", size_of::<Rc<RefCell<Debug>>>());
println!("{}", size_of::<Box<Rc<RefCell<Debug>>>>());
}它在64位机器上打印8, 16, 8。Playground link。
因为Rc在内部生成了一个Box (使用into_raw_non_null),所以我认为这会输出8, 8, 8。至少从size_of的角度来看,胖指针似乎从Debug向外渗透,甚至超过了Rc的Box,是不是因为它被存储为原始指针?
发布于 2019-01-17 03:14:05
归根结底,Rc<RefCell<Debug>>是特征对象,特征对象是胖指针。它内部和外部的类型都不是胖指针。
无论如何,在Vec<u8>集合中没有胖指针。Vec<T>是(*mut T, usize, usize),RefCell<T>是(T, usize),Rc<T>是(*mut T)。
size_of | is
---------------------+---
Vec<u8> | 24
RefCell<Vec<u8>> | 32
Rc<RefCell<Vec<u8>>> | 8您的第二个和第三个案例确实涉及到一个特征对象的胖指针:Rc<RefCell<dyn Debug>>。将一个特征对象放在另一个指针( Rc)后面会创建一个指向具体类型的瘦指针:*mut RefCell<dyn Debug>。
size_of | is
----------------------------+---
Rc<RefCell<dyn Debug>> | 16
Box<Rc<RefCell<dyn Debug>>> | 8值得注意的是,创建RefCell<dyn Debug>是不可能的
error[E0277]: the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time
--> src/main.rs:4:20
|
4 | println!("{}", mem::size_of::<RefCell<dyn Debug>>());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `std::cell::RefCell<dyn std::fmt::Debug>`, the trait `std::marker::Sized` is not implemented for `dyn std::fmt::Debug`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because it appears within the type `std::cell::RefCell<dyn std::fmt::Debug>`
= note: required by `std::mem::size_of`特征对象需要一些间接性;当您添加一些时,您最终构造了某种类型的胖指针。
您可以使用不稳定选项-Z print-type-sizes来探索结构的布局:
type: `std::rc::RcBox<std::cell::RefCell<dyn std::fmt::Debug>>`: 24 bytes, alignment: 8 bytes
field `.strong`: 8 bytes
field `.weak`: 8 bytes
field `.value`: 8 bytes
type: `core::nonzero::NonZero<*const std::rc::RcBox<std::cell::RefCell<dyn std::fmt::Debug>>>`: 16 bytes, alignment: 8 bytes
field `.0`: 16 bytes
type: `std::ptr::NonNull<std::rc::RcBox<std::cell::RefCell<dyn std::fmt::Debug>>>`: 16 bytes, alignment: 8 bytes
field `.pointer`: 16 bytes
type: `std::rc::Rc<std::cell::RefCell<dyn std::fmt::Debug>>`: 16 bytes, alignment: 8 bytes
field `.ptr`: 16 bytes
field `.phantom`: 0 bytes, offset: 0 bytes, alignment: 1 bytes
type: `std::cell::RefCell<dyn std::fmt::Debug>`: 8 bytes, alignment: 8 bytes
field `.borrow`: 8 bytes
field `.value`: 0 bytes我不是100%地解析这个输出,因为我希望RefCell<dyn Debug>是一个没有大小的类型(如上面的错误所示)。我假设"0字节“的含义是重载的。
https://stackoverflow.com/questions/54222831
复制相似问题