我已经检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>)所有这些都是16。大概它们只是将元素按顺序放入元组,因此由于对齐而浪费了一些空间。
如果元组在内部像这样存储元素:int, int, char, char,则其sizeof可能为12。
实现有可能执行此操作,还是该标准中的某些规则禁止这样做?
struct A
{
int a = 1;
short b = 2;
char c = 3;
}
struct B
{
using arr_type = array<A,3>;
char asd = 0;
A a1;
A a2;
A a3;
// is this safe to use to loop trough all 3 elements?
arr_type* p1 = reinterpret_cast<arr_type*>(&a1);
// or maybe this one?
A* p2 = &a1;
};
Run Code Online (Sandbox Code Playgroud)
我可以安全地使用p1或p2循环播放a1...a3吗?
B b;
for (int i = 0; i < 3; i++)
{
cout << …Run Code Online (Sandbox Code Playgroud) 经过一番调查后,我发现C++ 0x将元素向后存储在元组中.
例如,请使用以下代码:
std::tuple<char, char, char> x('\0', 'b', 'a');
char* y = (char*)&x;
std::cout << sizeof(x) << std::endl;
std::cout << y << std::endl;
Run Code Online (Sandbox Code Playgroud)
使用GCC 4.5.2编译时,我得到以下输出:
3
ab
Run Code Online (Sandbox Code Playgroud)
这最初困惑了我.为什么数据会向后存储?在通过GNU无意识混淆的标头搜索之后,我注意到实现类似于:
template<typename head, typename... tail> class tuple<head, tail...> : public tuple<tail...>
{
head value;
...
};
Run Code Online (Sandbox Code Playgroud)
因为基类包含最后一个元素,所以下一个派生类包含倒数第二个,等等,模板参数的实际顺序是相反的.
当我第一次进入元组时,我认为我可以将它们用于类似函数glInterleavedArrays(),它将顶点数据数组设置为颜色,纹理坐标,法线和点的元组.当然,如果我创建一个元组数组,这些数据必须反向输入,如果你碰巧忘记按正确的顺序放置参数,这可能会导致非常奇怪的错误.
那么这样的事呢?
template<typename... head, typename tail> class tuple<head..., tail> : public tuple<head...>
{
tail value;
...
};
Run Code Online (Sandbox Code Playgroud)
根据GCC 4.5.2:
std::tuple<char, char, char> x('\0', 'b', 'a');
char* y = (char*)&x;
std::cout << sizeof(x) << std::endl; …Run Code Online (Sandbox Code Playgroud) 因此,OpenGL编程的一个关键要求是以一种保证连续内存的方式存储顶点.我最近看过专业图形程序员的几本不错的书,他们都使用了相同想法的变体:将顶点打包成struct3 floats,x,y,z,然后将多个顶点打包成c风格阵列或std::vector这些structs.它有效.
但我已经看到它在这个网站上一次又一次地说struct,不保证内存连续性.有人说,如果你的结构包含所有,floats那么它们可能是连续的,但不能保证. 该array和std::vector你保证它,但是这无关紧要,如果你正在投入数组或向量是不连续的.
对于生产代码,我希望" 可能 "不会削减它.因此,尽管这两本书中的建议显然更适合学习,但我想知道还有哪些其他好的技术可以方便地组织顶点数据以保证连续的内存,或者,我接受建议我不应该担心这一点,这可能应该足够好了.
图形领域中使用的其他常用和好方法有哪些?