类将数据成员存储在顺序内存中?

2022-01-09 00:00:00 opengl pointers opengl-es c++

这个问题的简短版本:指向类的第一个数据成员的指针是否会导致指向其所有数据成员的指针?

讨论:

我正在阅读一些示例代码,这很有趣.当一个特定的函数(在本例中是来自 OpenGL 的 glUniformMatrix4fv C 函数)将一个数组作为参数时,它会以常用的 C 方式传递,即使用指向数组第一个元素地址的指针,如下:

glUniformMatrix4fv(glvariable, 1, 0, &newmatrix[0]);//指newmatrix

这个开发者有一个用于创建 4X4 矩阵的 C++ 类,总共有 16 个浮点数.但是,该类的数据成员被分成 4 个独立的向量,每个向量有 4 个数据成员:

以下是类的数据成员:

vec4 x;vec4 y;vec4z;vec4 w;

vec4 类依次提供这些数据成员:

T x;y;Tz;Tw;

然后他创建了一个函数来指向第一个 vec4 x 数据成员:

 const T* Pointer() const{返回 &x.x;}

不知何故,这奇迹般地转化为发送所有 4 个 vec4 对象及其各自的 4 个组件:

glUniformMatrix4fv(modelviewUniform, 1, 0, modelviewMatrix.Pointer());

我对 C++ 还很陌生,但令我惊讶的是,您可以只指向一个数据成员并期望所有其他数据成员也能发送.是因为该类以特定顺序定义它们吗?如果它们在类定义中以不同的顺序定义会怎样?

解决方案

这是 C++ 对象模型.您可以保证在相同的访问级别(private/public/protected)中,对象属性是有序的(C++11),对于它们之间没有访问说明符的成员也是如此(在 C++03 中).

这并不意味着您正在做的事情是一个好主意.最好避免强制转换,让函数做更多的工作.

C++11:

9.2 类成员 [class.mem]

<块引用>

14) 具有相同访问控制(第 11 条)的(非联合)类的非静态数据成员被分配,因此后来的成员在类对象中具有更高的地址.非静态数据的分配顺序未指定具有不同访问控制的成员 (11).实施对齐要求可能导致两个相邻的成员不被紧随其后地分配;所以可能要求用于管理虚函数 (10.3) 和虚基类 (10.1) 的空间.

C++03

9.2 类成员 [class.mem]

<块引用>

12) 在没有中间访问说明符的情况下声明的(非联合)类的非静态数据成员被分配,因此后来的成员在类对象中具有更高的地址.非静态数据的分配顺序由访问说明符分隔的成员未指定 (11.1).实施对齐要求可能导致两个相邻的成员不被紧随其后地分配;所以可能要求用于管理虚函数 (10.3) 和虚基类 (10.1) 的空间.

The short version of this question: Does a pointer to the first data member of a class result in a pointer to all its data members?

Discussion:

I'm reading some sample code, and this is interesting. When a particular function (in this case the glUniformMatrix4fv C function from OpenGL) takes as a parameter an array, this is passed in the common C way of using a pointer to the address of the array's first element, as follows:

glUniformMatrix4fv(glvariable, 1, 0, &newmatrix[0]); // referring to newmatrix

This developer has a C++ class for creating a 4X4 matrix, for a total of 16 floats. However, the data members of that class are divided into 4 separate vectors of 4 data members each:

Here are the data members of the class:

vec4 x;
vec4 y;
vec4 z;
vec4 w;

The vec4 class in turn provides these data members:

T x;
T y;
T z;
T w;

He then creates a function to point to just the first vec4 x data member:

    const T* Pointer() const
{
    return &x.x;
}

And somehow, this miraculously translates into sending all 4 vec4 objects and their respective 4 components:

glUniformMatrix4fv(modelviewUniform, 1, 0, modelviewMatrix.Pointer());

I'm fairly new to C++ but this surprised me that you can point to just one data member and expect all the rest to get sent as well. Is it because the class defines them in a particular order? What if they had been defined in a different order in the class definition?

解决方案

This is the C++ object model. You're guaranteed that within the same access level (private/public/protected), the object properties are in order (C++11), and the same for members without access specifiers between them (in C++03).

This doesn't mean what you're doing is a good idea. It's better to avoid the cast and just have the function do some more work.

C++11:

9.2 Class members [class.mem]

14) Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

C++03

9.2 Class members [class.mem]

12) Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

相关文章