首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么脂肪指针有时会向外渗透?

为什么脂肪指针有时会向外渗透?
EN

Stack Overflow用户
提问于 2019-01-17 02:02:38
回答 1查看 125关注 0票数 4

我认为我已经理解了Rust中的胖指针,但我无法理解为什么它们似乎从内部类型向外渗透。大概我的心理模型是关闭的,但我正在努力为这段代码找到一个令人满意的解释:

代码语言:javascript
复制
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, 8Playground link

因为Rc在内部生成了一个Box (使用into_raw_non_null),所以我认为这会输出8, 8, 8。至少从size_of的角度来看,胖指针似乎从Debug向外渗透,甚至超过了RcBox,是不是因为它被存储为原始指针?

EN

回答 1

Stack Overflow用户

发布于 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)

代码语言:javascript
复制
size_of              | is
---------------------+---
           Vec<u8>   | 24
   RefCell<Vec<u8>>  | 32
Rc<RefCell<Vec<u8>>> |  8

您的第二个和第三个案例确实涉及到一个特征对象的胖指针:Rc<RefCell<dyn Debug>>。将一个特征对象放在另一个指针( Rc)后面会创建一个指向具体类型的瘦指针*mut RefCell<dyn Debug>

代码语言:javascript
复制
size_of                     | is
----------------------------+---
    Rc<RefCell<dyn Debug>>  | 16
Box<Rc<RefCell<dyn Debug>>> |  8

值得注意的是,创建RefCell<dyn Debug>是不可能的

代码语言:javascript
复制
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来探索结构的布局:

代码语言:javascript
复制
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字节“的含义是重载的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54222831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档