Struct 选项类型是否小于包装类型加上布尔值? 使用std::mem::size\u of; 结构位置{ x:f32, y:f32, z:f32, } 结构池项{ 实体id:u32,//4字节 used:bool,//1字节+3(填充) 组件:位置,//12字节 } 断言!(尺寸为::(),4); 断言!(尺寸为::(),12); 断言!(尺寸::(),20);

Struct 选项类型是否小于包装类型加上布尔值? 使用std::mem::size\u of; 结构位置{ x:f32, y:f32, z:f32, } 结构池项{ 实体id:u32,//4字节 used:bool,//1字节+3(填充) 组件:位置,//12字节 } 断言!(尺寸为::(),4); 断言!(尺寸为::(),12); 断言!(尺寸::(),20);,struct,rust,boolean,padding,optional,Struct,Rust,Boolean,Padding,Optional,如您所见,这样的结构有20个字节长位置实际上是可选的,取决于使用的 使用是否会删除used字段的需要,并将结构大小减少到16 struct-PoolItem{ 实体id:u32,//4字节 组件:选项,//12字节? } 如果是这样,如何实现选项使这种行为起作用 我的测试似乎表明它不起作用。为什么?选项的精确实现其实并不重要。很明显,您不能在X存储量中存储X数据量,也不能存储数据是否存在。选项的一个明显实现是同时存储对象和一个指示对象是否存在的布尔值;显然,类似的事情正在发生选项很方便,它仍然

如您所见,这样的结构有20个字节长<代码>位置实际上是可选的,取决于使用的

使用是否会删除
used
字段的需要,并将结构大小减少到16

struct-PoolItem{
实体id:u32,//4字节
组件:选项,//12字节?
}
如果是这样,如何实现
选项
使这种行为起作用


我的测试似乎表明它不起作用。为什么?

选项的精确实现其实并不重要。很明显,您不能在
X
存储量中存储
X
数据量,也不能存储数据是否存在。
选项
的一个明显实现是同时存储对象和一个指示对象是否存在的布尔值;显然,类似的事情正在发生<代码>选项很方便,它仍然需要将信息存储在某个地方


请注意,如果优化器确定
选项
始终处于已知的“已填充或未填充”状态,则在
结构
(必须具有一致的大小)之外,
选项
可能会避免此成本,因此布尔值可能会被省略,而代码总是以正确的方式确定地使用它(如果对象在逻辑上存在,则从堆栈中读取该对象;如果对象不存在,则不读取该对象)。但在这种情况下,需要额外的数据。

选项的精确实现并不重要。
的一个明显的实现是,您不能在
X
存储量中存储
X
数据量,也不能存储数据是否存在。
选项的一个明显实现是存储对象和指示对象是否存在的布尔值;很明显,类似的情况正在发生。
选项
是一种方便,它仍然必须将信息存储在某个地方

请注意,如果优化器确定
选项
始终处于已知的“已填充或未填充”状态,则在
结构
(必须具有一致的大小)之外,
选项
可能会避免此成本,因此布尔值可能会被省略,而代码总是以正确的方式确定地使用它(如果对象在逻辑上存在,则从堆栈中读取对象,如果不存在则不读取对象)。但在这种情况下,需要额外的数据。

选项
需要存储状态(
部分
)在某个地方,由于
Position
已经包含12个字节的信息,您需要更多的空间来存储它。通常这意味着它会添加一个额外的字节(加上填充)存储状态,但在某些情况下,内部类型具有已知的未使用状态。例如,引用可以指向地址
0
,因此
选项u32{
self.entity\u id&!COMPONENT\u USED\u位
}
///设置实体ID,保留现有的“已使用组件”位
fn设置实体id(&mut self,实体id:u32){
让component_used_bit=self.entity_id&component_used_bit;
self.entity_id=(entity_id&!COMPONENT_USED_BIT)| COMPONENT_USED_BIT;
}
///如果设置了“已使用组件”位,则获取组件
fn组件(自身)->选项{
如果self.entity\u id&COMPONENT\u USED\u BIT!=0{
Some(&self.component)
}否则{
没有一个
}
}
///设置组件,更新“已使用组件”位
fn集合组件(&mut self,组件:选项){
如果让某些(组件)=组件{
self.component=组件;
self.entity_id |=组件_USED_位;
}否则{
self.entity\u id&=!COMPONENT\u USED\u BIT;
}
}
}
选项
需要将状态(
部分
)存储在某个地方,因为
位置
已经包含12个字节的信息,您需要更多的空间来存储它。通常这意味着它会添加一个额外的字节(加上填充)存储状态,但在某些情况下,内部类型具有已知的未使用状态。例如,引用可以指向地址
0
,因此
选项u32{
self.entity\u id&!COMPONENT\u USED\u位
}
///设置实体ID,保留现有的“已使用组件”位
fn设置实体id(&mut self,实体id:u32){
让component_used_bit=self.entity_id&component_used_bit;
self.entity_id=(entity_id&!COMPONENT_USED_BIT)| COMPONENT_USED_BIT;
}
///如果设置了“已使用组件”位,则获取组件
fn组件(自身)->选项{
如果self.entity\u id&COMPONENT\u USED\u BIT!=0{
Some(&self.component)
}否则{
没有一个
}
}
///设置组件,更新“已使用组件”位
fn集合组件(&mut self,组件:选项){
如果让某些(组件)=组件{
self.component=组件;
self.entity_id |=组件_USED_位;
}否则{
self.entity\u id&=!COMPONENT\u USED\u BIT;
}
}
}

正如评论中所建议的,另一种选择是使用
选项
和for
实体id
,并依靠
部分
检查实体是否被使用

struct-PoolItem{
实体id:选项,//4字节
组件:位置,//12字节
}
fn main(){
断言(大小为:(),4);
断言(大小:(),12);
断言(大小:(),16);
}
它使实体ID从
1
开始


正如评论中所建议的