请考虑以下事项:
#include <vector>
using namespace std;
struct Vec2
{
float m_x;
float m_y;
};
vector<Vec2> myArray;
int main()
{
myArray.resize(100);
for (int i = 0; i < 100; ++i)
{
myArray[i].m_x = (float)(i);
myArray[i].m_y = (float)(i);
}
float* raw;
raw = reinterpret_cast<float*>(&(myArray[0]));
}
raw
是否保证有200个具有正确值的连续浮点数?也就是说,标准是否保证这一点?
编辑:如果保证上述内容,并且Vec2
有一些函数(非虚拟)和构造函数,那么保证仍然存在吗?
注意:我意识到这很危险,在我的特殊情况下,我没有 我正在选择第三方图书馆。
答案 0 :(得分:5)
我意识到这很危险,在我的特殊情况下,我没有选择,因为我正在使用第三方库。
您可以添加结构大小的编译时检查:
struct Vec2
{
float a;
float b;
};
int main()
{
int assert_s[ sizeof(Vec2) == 2*sizeof(float) ? 1 : -1 ];
}
这会增加你对你的方法的信心(由于reinterpret_cast,这仍然是不安全的,如上所述)。
raw = reinterpret_cast(&amp;(myArray [0]));
ISO C ++ 98 9.2 / 17:
指向POD结构对象的指针(适当地使用 reinterpret_cast 转换)指向其初始成员(或者如果该成员是位字段,则指向它所在的单位)和反之亦然。 [注意:因此,在标准布局结构对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐。 - 后注]
最后,相应地址的运行时检查会使这种解决方案相当安全。它可以在单元测试期间甚至在程序的每个开始时(在小型测试阵列上)完成。
全部放在一起:
#include <vector>
#include <cassert>
using namespace std;
struct Vec2
{
float a;
float b;
};
int main()
{
int assert_s[ sizeof(Vec2) == 2*sizeof(float) ? 1 : -1 ];
typedef vector<Vec2> Vector;
Vector v(32);
float *first=static_cast<float*>(static_cast<void*>(&v[0]));
for(Vector::size_type i,size=v.size();i!=size;++i)
{
assert((first+i*2) == (&(v[i].a)));
assert((first+i*2+1) == (&(v[i].b)));
}
assert(false != false);
}
答案 1 :(得分:3)
不,这不安全,因为编译器可以在结构中的两个float
之间或之后插入填充,因此结构的float
可能不是连续的。
如果您仍想尝试它,可以添加编译时检查以增加更多保证它将起作用:
static_assert(sizeof(Vec2) == sizeof(float) * 2, "Vec2 struct is too big!");
static_assert(offsetof(Vec2, b) == sizeof(float), "Vec2::b at the wrong offset!");
答案 2 :(得分:-1)
reinterpret_cast
给出的唯一保证是,当您将已转换对象reinterpret_cast
返回到原始数据类型时,您将获得原始对象。
特别是,raw
不能保证有200个具有正确值的连续浮点数。