关于内存:C ++ 0x元组向后存储元素

C++0x Tuples Store Elements Backwards

经过一番调查后,我发现C++0x在内存中将元组中的元素存储在后台。

例如,采用以下代码:

1
2
3
4
std::tuple<char, char, char> x('\0', 'b 'a');
char* y = (char*)&x;
std::cout << sizeof(x) << std::endl;
std::cout << y << std::endl;

当使用GCC4.5.2编译时,我得到以下输出:

1
2
3
ab

这起初让我困惑。为什么数据是向后存储的?在浏览了GNU无意中混淆的头部之后,我注意到实现与此类似:

1
2
3
4
5
template<typename head, typename... tail> class tuple<head, tail...> : public tuple<tail...>
{
  head value;
  ...
};

因为基类包含最后一个元素,那么下一个派生类包含从第二个到最后一个的元素,等等,所以模板参数的实际顺序是相反的。

当我第一次进入元组时,我认为我可以将它们用于像glInterleavedArrays()这样的函数,它将顶点数据数组设置为颜色、纹理坐标、法线和点的元组。当然,如果我创建了一个元组数组,则必须反向输入这些数据,如果您碰巧忘记将参数按正确的顺序放置,则可能会导致非常奇怪的错误。

那么像这样的东西呢?

1
2
3
4
5
template<typename... head, typename tail> class tuple<head..., tail> : public tuple<head...>
{
  tail value;
  ...
};

根据GCC 4.5.2:

1
error: parameter pack argument ‘head ...’ must be at the end of the template argument list

除非这在将来可用,否则我会一直在寻找另一种方法来实现它。还有别的办法吗?有什么方法可以欺骗gcc获得一个正确排序的元组内存?


您正在探索的tuple布局是tuple的未指定实现细节。其他实现将具有其他布局。如果您写这个代码,根据GCC的布局,您的代码可能无法移植到其他std::libs。

libc++元组实现(例如)的布局与之相反(按顺序)。


为什么您关心tuple的实现是什么?程序到接口,而不是实现。

如果您只通过其公布的接口使用tuple,那么您将按照放入它们的相同顺序取出对象。如果您改为通过直接访问封装的内容来破坏封装,例如通过示例中的Dodgy指针来破坏封装,那么所有的赌注都是关闭的。