我已经检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>)
在它们中都是16。据推测,它们只是按顺序将元素放入元组中,因此由于对齐而浪费了一些空间。
如果元组内部存储的元素形如:int, int, char, char
,那么它的 sizeof 可能为12。
这种实现方式是否可行,或者是否被标准中的某些规则禁止?
我已经检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>)
在它们中都是16。据推测,它们只是按顺序将元素放入元组中,因此由于对齐而浪费了一些空间。
如果元组内部存储的元素形如:int, int, char, char
,那么它的 sizeof 可能为12。
这种实现方式是否可行,或者是否被标准中的某些规则禁止?
std::tuple的sizeof,这是一个被忽视的优化吗?
是的。
实现是否可能做到这一点?
是的。
在[tuple]中阅读,没有对实现存储成员的模板参数顺序放置任何约束。
事实上,我能找到的每个段落似乎都尽力避免对成员声明顺序进行任何引用:get<N>()
在操作语义的描述中使用。其他措辞以“元素”而不是“成员”为基础,这似乎是一个非常明确的抽象。
实际上,一些实现显然会反向存储成员, 至少可能仅是由于它们递归地使用继承来解压缩模板参数的方式(并且因为,如上所述,它们被允许这样做)。
具体来说,关于你的假设优化,我不知道是否有任何实现不存储元素在用户给定的顺序中的情况;我猜想相比于从中获得的收益,想出这样的顺序并提供std::get
的机制会比较困难。如果你真的担心填充问题,当然可以仔细选择元素顺序以避免它(在某个特定平台上),就像处理类一样(而不涉及“压缩”属性的世界)。(“压缩”元组可能是一个有趣的建议……)
他们可以这样做。他们不这样做的一个可能原因是,一些架构(包括x86)具有索引模式,可以在单个指令中寻址地址base + size × index,但前提是size是2的幂。或者,如果进行对齐到16字节边界的加载或存储,则可能会稍微快一些。如果它们添加了四个填充字节,这可能会使处理std::tuple
数组的代码略微更快且更紧凑。
struct
和tuple
之间有很大的区别=>一个是语言结构,另一个是库类型。你为什么认为它们必须遵守相同的规则呢? - Matthieu M.