跨越结构向量的成员

Posted

技术标签:

【中文标题】跨越结构向量的成员【英文标题】:Striding across members of a vector of structures 【发布时间】:2013-10-23 14:30:11 【问题描述】:

有没有一种简单的方法可以按成员跨越结构的 STL 向量?换句话说,如果我有这样的结构:

struct foo 
    double x, y, z;
;

在向量std::vector<foo> bar(20) 中,我可以跨过数组从每个结构中挑选出 x 吗?

我试过了,但它似乎不起作用:

for (int i=0; i<20; ++i)

   double xx = (&bar[0].x + i*sizeof(bar[0]))->x;

为什么这不起作用? sizeof(bar[0]) 不考虑结构之间的填充吗?

注意:我意识到这是在循环中访问 x 的一种非常愚蠢的方式,但这个循环只是一个实验,看看 stride 是否有效。

如果有帮助,我想这样做,这样我就可以将 bar 传递给一个库例程,该例程接受一个指针和一个 stride 作为构造函数参数到它自己的内部数据类型。当然,我可以将我的代码从 AoS 转换为 SoA,但我不想这样做,除非万不得已。

【问题讨论】:

sizeof 不包括填充,因为填充也可以取决于数据结构中前后的内容。您也许可以改为“int size = (char*)&bar[1] - (char*)&bar[0]”?不确定这是否合法,这就是为什么这是评论而不是答案。 每当我看到一些“聪明”的东西时,我都想知道为什么有人要让一些东西更加晦涩不易维护 再一次,我真的需要开始和跨步传递给我无法控制的第 3 方库。该循环只是一个经验测试,以确认它是否有效,而不是试图变得聪明。 sizeof(bar[0]) 不考虑结构之间的填充吗?”。它确实说明了这一点,问题是 Andrey 和 user1735003 所说的指针类型。保证数组或向量的成员之间没有填充,并且任何填充 inside foo 都包含在 sizeof(bar[0]) 中。 @jcode:只要vector至少有两个元素是合法的,并且保证等于sizeof(foo) 【参考方案1】:

我想我会直接计算步幅,使用类似的东西:

struct point 
    double x, y, z;
;

int main() 
    point points[2];

    std::cout << "stride = " << (char *)(&(points[1].x)) - (char *)(&(points[0].x)) << "\n";

【讨论】:

【参考方案2】:

&amp;bar[0].x 是一个指向 double 的指针。您正在向其添加 i*sizeof(bar[0])

效果是指针中存储的地址增加了i*sizeof(bar[0])*sizeof(double),这不是你所期望的。

正确的表达方式是

&bar[0].x + i*sizeof(bar[0])/sizeof(double)

【讨论】:

虽然bar 有一个double 成员,但sizeof(bar) 不是sizeof(double) 的倍数是不太可能的,但标准允许。当然,对于这个特定的类来说尤其不可能,因为它没有不是 doubles 的成员。【参考方案3】:

&bar[0].x 是一个指向 double 的指针。要添加适当的班次,您需要将其转换为 char*,然后再次加倍 *。

     double xx = *reinterpret_cast<double*>(reinterpret_cast<char*>(&bar[0].x) + i*sizeof(bar[0]));

无论如何,您应该真正考虑使用标准算法来达到您的目的。

【讨论】:

我需要跨度和初始指针作为第 3 方库的参数。这真的是我所追求的步幅(和初始指针)。循环只是一个经验测试。 好的。然后一切都在这里:步幅只是sizeof(foo),不需要算术。您可以从reinterpret_cast&lt;char*&gt;(&amp;bar[0].x) 开始。我个人喜欢使用reinterpret_cast。它在这里清楚地宣传我们正在处理非标准的低级技术。 填充呢? sizeof(foo) 是我尝试的第一件事,但它不起作用,因此更改为 sizeof(bar[0])。 它没有用,所以你改为sizeof(bar[0])...它仍然没有工作,因为这不是它没有工作的原因:) sizeof(foo) 是等价的在本例中为 sizeof(bar[0])。它应该可以正常工作。

以上是关于跨越结构向量的成员的主要内容,如果未能解决你的问题,请参考以下文章

Python zipfile 模块错误地认为我有一个跨越多个磁盘的 zipfile,抛出 BadZipfile 错误

算法:找到仅由它们的分离定义的最小空间跨越点

2021银行共探转型新动能:大行酝酿质变 小行跨越数字鸿沟

字节对齐

重大跨越!Windows 11 23H2 25115 推送:2023 年更新测试开启,水印回归

探秘VOOPOO创新基因 解码跨越式发展