为什么 Nil 会增加一个枚举大小而不增加另一个枚举大小? Rust 枚举的内存是如何分配的?

2024-05-19

如果我定义以下枚举,Nil 不会增加枚举的大小:

  use std::mem::size_of;

  enum Foo {
    Cons(~char)
  }

  enum Bar {
    Cons(~char),
    Nil
  }

  println!("{}", size_of::<Foo>());
  println!("{}", size_of::<Bar>());

  // -> 4
  // -> 4

另一方面:

  enum Foo {
    Cons(char)
  }

  enum Foo {
    Cons(char),
    Nil
  }

Yields:

  // -> 4
  // -> 8

当我定义枚举时会发生什么?如何为这些结构分配内存?


枚举的一种简单方法是为其最大变体的内容以及判别式分配足够的空间。这是一个标准标记联盟.

Rust 比这聪明一点。 (它可能会更聪明,但目前还不是。)它知道给定一个~T,该内存位置至少有一个值cannot是:零。所以在像你这样的情况下enum { Cons(~T), Nil },它能够将其优化为一个字,并且内存中的任何非零值都有意义Cons(~T)以及内存意义中的零值Nil.

当你处理char,优化无法发生:零是有效的代码点。当它发生的时候,char被定义为 Unicode 代码点,所以它would实际上可以将变体优化到该空间中,最后有大量的备用位(Unicode 字符只需要 21 位,因此在 32 位空间中我们有 11 个备用位)。这证明了 Rust 的枚举判别式优化目前还不是特别聪明。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Nil 会增加一个枚举大小而不增加另一个枚举大小? Rust 枚举的内存是如何分配的? 的相关文章

  • 为什么 String 不实现 From<&String>?

    背景 我知道 Rust 人们更喜欢 str而不是 String 但在某些情况下我们只得到 String 一个例子是当你打电话时std iter Iterator peekable 返回值是一个Peekable i 将原始迭代器包装到其中并为
  • 跨 dll 边界的内存分配和释放

    我知道在一个 dll 中进行内存分配然后在另一个 dll 中释放内存可能会导致各种问题 尤其是与 CRT 相关的问题 当涉及到导出 STL 容器时 此类问题尤其成问题 我们之前遇到过此类问题 在编写与我们的库链接的自定义 Adob e 插件
  • 从所有者对象读取时可变的自身

    我有一个对象拥有另一个对象 拥有的对象有一个可变方法 该方法依赖于其所有者的非可变方法 架构 尽可能简化 如下所示 struct World animals Vec
  • 在 Swift 中,当使用“[weak self] in”时,当嵌套在另一个闭包中时我是否应该加倍它[重复]

    这个问题在这里已经有答案了 在 Swift 中 当使用 weak self in 当嵌套在另一个闭包中时 我应该将其加倍吗 Example override func viewDidLoad super viewDidLoad makeAP
  • 在结构定义上指定“Fn”特征绑定,而不修复“Fn”参数之一

    我有一个包含函数对象的结构 struct Foo
  • 如何对另一个数字进行模运算而不溢出?

    我正在尝试为 Rust 实现快速素性测试u32 and u64数据类型 作为其中的一部分 我需要计算 n n d where n and d are u32 or u64 分别 虽然结果可以很容易地适合数据类型 但我不知道如何计算它 据我所
  • 如何使用diesel-rs选择色谱柱的子集?

    我现在花了几个小时的时间来查询表的可用列的子集以及在其中包含计算 我知道这不是在选择查询中执行计算的最佳方式 但现在 我只是在开发一个原型 它应该是可行的 我在用diesel rs作为后端实现中所有数据库操作的 ORM 数据将存储在 Pos
  • 如何在不使用 Box 的情况下从特征方法返回匿名类型?

    我有一个扩展特征 其方法只是适配器 组合器的简写 fn foo self gt self map i i 2 foo bar 返回类型为Trait foo 是一些嵌套的Map
  • 仅当处于发布模式时,我如何在没有窗口的情况下运行 Rust 程序[重复]

    这个问题在这里已经有答案了 我目前正在开发一个 Rust 项目 并且经常需要调试和部署它 虽然它已部署 但它在后台运行 没有窗口 但当我调试时 我想要一个窗口来查看是否存在任何运行时错误 我目前使用 windows subsystem wi
  • 无法返回对临时值的引用

    我正在尝试学习 Rust 同时我想尝试将结构对象转换为字节数组 但这样做遇到了问题 所以我有这个 struct Node lt a gt id u8 name a str data a str impl lt a gt Node lt a
  • Box、ref、&、*的理解及关系

    我对 Rust 中的指针如何工作有点困惑 有ref Box 而且我不确定他们如何一起工作 目前我的理解是这样的 Box并不是真正的指针 它是一种在堆上分配数据并在函数参数中传递未调整大小的类型 尤其是特征 的方法 ref在模式匹配中用于借用
  • '&&x' 模式匹配是否会导致 x 被复制?

    在文档中std iter 迭代器 filter https doc rust lang org stable std iter trait Iterator html method filter它解释了值通过引用传递给闭包 并且由于许多迭代
  • Glassfish 上的内存管理

    我的 Glassfish 服务器上运行着几个后台任务 由 TimerService实例 这些服务的目标是从文件中提取数据并将该数据插入数据库 我最初尝试在 JPA 中执行此操作 但系统很容易就停滞了 我现在已将该过程转换为 JDBC 它的响
  • 操作/Lambda 表达式内存管理问题

    我将一个操作存储在局部变量中 然后在该局部变量超出范围后使用 使用前是否有被清理的危险 这是一个例子 public List GetMaps Action
  • 转换位域结构的字节顺序

    我需要将位字段结构从小端架构转换为大端架构 最好的方法是什么 因为如果我只是交换结构元素 字节边界就会出现问题 前结构是 struct unsigned int b1 1 unsigned int b2 8 unsigned int b3
  • 在 Internet Explorer 中使用什么来监视 jscript 内存使用情况

    我们正在调试 GWT 应用程序 在 Firefox 中运行正常 在 IE6 0 中开始运行正常 但一段时间后 它就会崩溃并开始爬行 经过一些测试后 我们怀疑存在一些内存问题 使用了太多内存 内存泄漏等 除了使用taskmanager和pro
  • 这个函数(for循环)空间复杂度是O(1)还是O(n)?

    public void check 10 for string i list Integer a hashtable get i if a gt 10 hashtable remove i 这是 O 1 还是 O n 我猜测 O n 但不是
  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构

随机推荐