C++中类变量声明的查询
我有一个类来表示浮点数的 3D 向量:
class Vector3D
{
public:
float x, y, z;
float * const data;
Vector3D() : x(0.0), y(0.0), z(0.0), data(&x) {}
}
我的问题是:x、y 和 z 是否将在内存中按顺序分配,以便我可以将 x 的地址分配给数据,然后在数据上使用下标运算符以数组形式访问向量分量?
例如,有时我可能想直接访问向量分量:
Vector3D vec;
vec.x = 42.0;
vec.y = 42.0;
vec.z = 42.0;
有时我可能想通过偏移量访问它们:
Vector3D vec;
for (int i = 3; i--; )
vec.data[i] = 42.0;
第二个示例是否与第一个示例具有相同的效果,或者我是否会冒覆盖除x、y 和 z 是否浮动?
I have a class to represent a 3D vector of floats:
class Vector3D
{
public:
float x, y, z;
float * const data;
Vector3D() : x(0.0), y(0.0), z(0.0), data(&x) {}
}
My question is: are x, y, and z going to be allocated sequentially in memory such that I can assign the address of x to data and later use the subscript operator on data to access the vector components as an array?
For example, sometimes I may want to access the vector components directly:
Vector3D vec;
vec.x = 42.0;
vec.y = 42.0;
vec.z = 42.0;
And sometimes I may want to access them by offset:
Vector3D vec;
for (int i = 3; i--; )
vec.data[i] = 42.0;
Will the second example have the same effect as the first one, or do I run the risk of overwriting memory other than the x, y, and z floats?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不,这是未定义的行为,原因有两个:
但是,以下内容是有效的:
std::array
对于 C++0x 来说是新的,并且基本上等同于boost::array
。如果您不需要 C++0x 或 Boost,您可以使用std::vector
(并将初始化程序更改为data(3)
),尽管这是一个更重量级的解决方案,它的大小可以从外界修改,如果是的话,那么结果将是UB。No, this is undefined behaviour, for two reasons:
However, the following would be valid:
std::array
is new to C++0x, and is basically equivalent toboost::array
. If you don't want C++0x or Boost, you could use astd::vector
(and change the initializer todata(3)
), although that's a much more heavyweight solution, its size could be modified from the outside world, and if it is, then the result would result be UB.是的。这个类是
布局兼容标准布局,因为:public:
)中,因此,可以保证它像 C 结构一样按顺序布局。这允许您将文件头作为结构来读取和写入。
Yes. This class is
layout-compatiblestandard-layout, because:public:
)Because of this, it's guaranteed to be laid out sequentially just like a C structure. This is what allows you to read and write file headers as structures.
或者你可以有一个operator[]重载
or you can have an operator[] overload
编译器在如何布局结构中的内存方面具有一定的灵活性。该结构永远不会与另一个数据结构重叠,但它可以在元素之间注入未使用的空间。在您给出的结构中,某些编译器可能会选择在 z 和 data 之间添加 4 个字节的额外空间,以便数据指针可以对齐。大多数编译器都提供了一种紧密打包所有内容的方法。
编辑:不能保证编译器会选择紧密打包 x、y 和 z,但实际上它们会打包得很好,因为它们是结构体的第一个元素,并且因为它们是大小为二的幂。
The compiler has some flexibility in how it lays out the memory within a struct. The struct will never overlap another data structure, but it can inject unused space between elements. In the struct you give, some compilers might choose to add 4 bytes of extra space between z and data so that the data pointer can be aligned. Most compilers provide a way of packing everything tightly.
EDIT: There's no guarantee that the compiler will choose to pack x, y, and z tightly, but in practice they will be packed well because they are the first elements of the struct and because they're a power of two in size.
您的解决方案无效,但如果您可以确保(或知道)您的编译器将“做正确的事情”(特别是通过控制 x、y 和 z 元素之间的填充),那么您就可以了。在这种情况下,我会完全删除
data
成员并使用operator[]
。我有时见过类似的东西。它遇到了完全相同的问题,但确实节省了您存储数据指针的麻烦,并且允许使用更好的
v[0]
语法,而不是v.data[0]
。编辑:由 ildjam 提示,这里有一个使用访问器而不是成员的兼容版本,这是相似的。
Your solution is not valid, but if you can ensure (or know) that your compiler will "do the right thing" (in particular by controlling padding between the x, y and z elements) you will be ok. In this case though I'd remove the
data
member altogether and useoperator[]
.I've seen something like this used on occasion. It runs into exactly the same issues, but does save you storing that data pointer, and allows for a nicer
v[0]
syntax rather thanv.data[0]
.EDIT: Prompted by ildjam heres a compliant version using accessors rather than members, that is similar.
做这样的事情:
Do something like this: