查询C++中的类变量声明

mil*_*eft 5 c++ arrays variables subscript memory-address

我有一个类来表示浮动的3D矢量:

class Vector3D
{
    public:

    float x, y, z;
    float * const data;

    Vector3D() : x(0.0), y(0.0), z(0.0), data(&x) {}
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:x,y和z是否会在内存中顺序分配,这样我就可以将x的地址分配给数据,然后使用数据上的下标运算符来作为数组访问矢量组件?

例如,有时我可能想直接访问矢量组件:

Vector3D vec;
vec.x = 42.0;
vec.y = 42.0;
vec.z = 42.0;
Run Code Online (Sandbox Code Playgroud)

有时我可能想通过偏移来访问它们:

Vector3D vec;
for (int i = 3; i--; )
    vec.data[i] = 42.0;
Run Code Online (Sandbox Code Playgroud)

第二个示例是否与第一个示例具有相同的效果,或者我是否存在覆盖除x,y和z浮点数以外的内存的风险?

Oli*_*rth 6

不,这是未定义的行为,原因有两个:

  • 首先是其他人提到的填充问题.
  • 其次,即使事物被正确填充,取消引用具有偏移量的指针也是无效的,该偏移量将使其超出其指向的范围.编译器可以自由地假设这一点,并进行优化,如果您违反它,将导致未定义的行为.

但是,以下内容有效:

class Vector3D
{
public:
    std::array<float,3> data;
    float &x, &y, &z;

    Vector3D() : data(), x(data[0]), y(data[1]), z(data[2]) { }
    Vector3D& operator =(Vector3D const& rhs) { data = rhs.data; return *this; }
};
Run Code Online (Sandbox Code Playgroud)

std::array是C++ 0x的新手,基本上相当于boost::array.如果您不想要C++ 0x或Boost,您可以使用std::vector(并更改初始化程序data(3)),虽然这是一个更重要的解决方案,但它的大小可以从外部世界修改,如果是,那么结果将是UB.