3

考虑一个类:

template <typename T>
struct A{
  //...many public member functions...
  T x;
  T y;
  T z;
}

还有一个类似的:

template <typename T>
struct B{
  //many public member functions
  T x;
  T y;
}

虽然此处未指定,但T始终为floatorintbool

现在考虑另一个结构:

struct Pair{
  A<float> a;
  B<float> b;
 }

现在一个vector

 std::vector<Pair> bigBunch;

假设所有x, y, zinbigBunch将是连续的有多安全?我知道这vector保证了它Pair的 s 之间的连续内存,但我也知道这struct并不一定保证连续内存,因为可能会发生填充。struct但是,我认为只有当您的元素是不同类型时,填充才是一种风险。

我希望能够获得一个指针bigBunch[0].a.x,然后知道我可以期望floats 的整个内容中有一个连续的流bigBunch。实际上,指向的指针与bigBunch[0].a.x刚才说的指向同一个地方`bigBunch[0].a

Pair.a和是相同类型还是不同类型是否重要Pair.b,例如混合intsfloat而不是两者都是相同类型(float在本例中)?

4

3 回答 3

1

但是,我认为只有当你的结构元素是不同类型时,填充才是一种风险。

这不是很准确,它主要与所有内容在内存中占用多少空间有关。

您的示例使用float4 个字节,因此不会导致填充。填充的全部目的是加快内存访问,4 字节边界上的 4 字节对象很好。

所以你应该能够假设你有一个流float,但你可能不会如果Pairwhere on bool。我这么说的原因是因为它可能决定b在 4 字节边界上效果最好,这会引入一个字节的填充。

于 2013-04-04T04:03:51.003 回答
1

AFAIK,如果编译器认为这是一个好主意,标准中的任何内容都不会阻止编译器添加填充。编译器在这件事上确实有很大的余地。这意味着最好的做法是防御并明确指示编译器打包数据,即使例如 4 字节边界上的 4 字节浮点数不应导致填充。

我的另一个建议是用来static_assert验证一切都是你想要的大小。例如,

template <typename T>
struct A{
  //...many public member functions...
  T x;
  T y;
  T z;
} __attribute__ ((__packed__));
static_assert(sizeof(A) == 3*sizeof(T), "struct A shouldn't be padded");

如果您没有 C++ 11,则可以BOOST_STATIC_ASSERT改用。编辑:__attribute__ ((__packed__))结构的右大括号后的位是 GCC 特定的确保结构紧凑的方式。

您应该考虑的另一件事是,您是否真的从能够将您的数组视为一个没有间隙vector<Pair>的大数组中受益。float我知道如果您必须遍历所有内容,或者如果您必须将数据传递给其他需要连续数据的库,这可能会使一些算法更方便编写。但我猜你正在用这些结构做很多数学运算,你的编译器可能能够自动矢量化其中的一些,例如,如果struct A是 128 位对齐,则使用 SSE。在我的答案的这一部分中,我有很多猜测,所以如果它不适用于您,请忽略它。

PS:不要忘记结构的右大括号后的分号。

于 2013-04-04T05:04:45.687 回答
1

假设 bigBunch 中的所有 x、y、z 都是连续的,这有多安全?

不安全。编译器可以自由填充。取决于T

指向 bigBunch[0].ax 的指针将指向与刚才说 `bigBunch[0].a 相同的位置。

这是安全的假设。

如果 Pair.a 和 Pair.b 是相同的类型还是不同的类型,例如混合 int 和 float 而不是两者都是相同的类型(本例中为 float),这有关系吗?

假设是不安全的。对于intand ,我们可能很幸运,但对于andfloat可能不是这样shortint

填充故事在 32 位机器和 64 位机器之间变化。如果您希望您的代码适用于所有架构,则不能对填充和对齐做出假设。

有关一般性讨论,请参阅http://en.wikipedia.org/wiki/Data_structure_alignment

总之,永远不要在你的程序中假设任何关于填充的事情:-)

于 2013-04-04T05:28:57.607 回答