public/private/protected 会改变结构在内存中的排列吗?

Do public/private/protected change the arrangement of a struct in memory?

编辑: 我刚刚意识到提出这个问题的一种更简单的方法:

Given the following two structs:

class Thing {public: int a; public: int b; public: int c;}

class Thing {public: int a, private: int b; public: int c;}

Are the members a, b, and c guaranteed to be in the same order in memory for both of these definitions?


老问题

假设我们在 fileA.cpp:

中有这个 C++ 代码
class Thing
{
public:
    int a;
    double num;

    Thing()
    {
        b = 10;
    }

    float getB()
    {
        return b;
    }

private:
    float b;
    Thing * other;
}

void doSomething(Thing thing);

int main()
{
    Thing thing;
    doSomething(thing);
    std::cout << thing.b;
}

假设我们在 fileB.cpp:

中有这段代码
class Thing
{
public:
    int a;
    double num;

    Thing()
    {
        b = 10;
    }

    float getB()
    {
        return b;
    }

    float b;

private:
    Thing * other;
}

void doSomething(Thing thing)
{
    thing.b = 30;
}

假设编译器不会报错,这段代码会按预期工作吗?也就是说,结构数据的排列是否独立于某些组件是 public、私有的还是受保护的?

编辑: 为了更明显,Thing 的两个定义之间的唯一区别是 float b;fileA.cpp 但 public 在 fileB.cpp.

标准没有做出这样的保证。您只有标准布局的布局保证 classes:

A standard-layout class is a class that:

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member.

(C++14, [class] ¶7)

如果一个class是标准布局,它的布局是明确定义的(并且两个具有布局兼容初始序列的标准布局class可以通过读取彼此的布局兼容成员union).

然而,这里不是这种情况,因为在 class 中您有不同的访问说明符。特别是,它明确指出

The order of allocation of non-static data members with different access control is unspecified

(C++14, [class.mem] ¶13)


话虽这么说,但我从未使用过任何利用标准提供的这种灵活性的现实世界编译器——我知道的每个编译器都使用访问说明符进行编译时检查, 但就成员布局而言完全忽略它们。