C++ 类与结构的内存布局如何
我来自C编程,在C编程中,结构中的数据首先使用顶部变量,然后是第二个、第三个,依此类推 我现在正在用C++编程,而我正在使用一个类。我基本上想达到同样的效果,但是我也想要GET/SET方法,也可能需要其他方法(我也想尝试用C++风格来做,并且可以学到一些新的东西)。 是否有保证,例如,公共变量首先在内存中,然后是私有变量 是否有保证,例如,公共变量将在 内存是私有变量吗 不,这样的保证不是C++11标准,[class.mem]/14: 具有相同访问权限的(非联合)类的非静态数据成员 控制权的分配(第11条),以便以后的成员拥有更高的控制权 类对象中的地址非静态数据的分配顺序 未指定具有不同访问控制的数据成员(11) 所以 仅保证对于类型为C++ 类与结构的内存布局如何,c++,c,class,struct,language-lawyer,C++,C,Class,Struct,Language Lawyer,我来自C编程,在C编程中,结构中的数据首先使用顶部变量,然后是第二个、第三个,依此类推 我现在正在用C++编程,而我正在使用一个类。我基本上想达到同样的效果,但是我也想要GET/SET方法,也可能需要其他方法(我也想尝试用C++风格来做,并且可以学到一些新的东西)。 是否有保证,例如,公共变量首先在内存中,然后是私有变量 是否有保证,例如,公共变量将在 内存是私有变量吗 不,这样的保证不是C++11标准,[class.mem]/14: 具有相同访问权限的(非联合)类的非静态数据成员 控制权的分配
a
的给定对象
的地址小于i
和j
的地址小于j
str
struct
和class
在布局方面没有任何区别:它们唯一的区别是仅在编译时存在的访问权限
它只表示顺序,但不表示第一个变量实际开始 在“第一个地址”?让我们假设一个没有继承的类 是,但仅适用于标准布局类。一个类要成为标准布局类必须满足一行要求,其中之一是所有成员都具有相同的访问控制。
引用C++14(同样适用于C++11,但措辞更为间接),[class.mem]/19: 如果标准布局类对象具有任何非静态数据成员,则其 地址与其第一个非静态数据的地址相同 成员。否则,其地址与第一个地址相同 基本类子对象(如果有)。[注:因此可能有 标准布局结构对象中的未命名填充,但不在其开头,这是实现适当对齐所必需的。-结束注释] [类别]/7: 标准布局类是指:
- 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员
- 没有虚拟函数(10.3)和虚拟基类(10.1)
- 对所有非静态数据成员具有相同的访问控制(第11条)
- 没有非标准布局基类
- 在最派生的类中没有非静态数据成员,并且最多有一个基类具有非静态数据成员,或者没有基类 具有非静态数据成员的类,以及
- 没有与第一个非静态数据成员类型相同的基类。110
第一件事:
如果您使类的所有数据成员都是私有的,并且添加访问器成员函数(即C++从其他语言调用的方法),那么您将达到这个效果。经验法则是将热变量放在顶部。类和结构之间的布局绝对没有区别。所以,如果我先定义公共变量,它们将在内存中处于第一位?我假设我可以通过这种方式访问私有成员?为什么你需要知道数据在内存中是如何排列的?我知道这很好理解,但在实践中,如果你需要知道的话,在很多情况下,这可能表明你做错了……如果类是“简单的”(可能满足Columbo提到的标准布局类标准),并且数组是一个字符数组(不是int数组或类似的数组),那么这应该是可能的。你基本上是在执行二进制(反)序列化,这并不少见。所以如果我有公共变量和私有变量,我不能假设它们是按顺序排列的?如果我只有公共或私人地址呢?那么他们的地址确实在增加。正如引用所说,它只说明顺序,而不是第一个变量实际上从“第一个地址”开始?让我们假设一个没有继承的类。@Phataas还添加了需求列表。这给了我很好的洞察力,并且解释得很好!我曾考虑使用该类从指向数组开头的指针强制转换到此类,但现在我不确定这是否可行,因为类中的访问器成员函数和其他可能的填充等占用了内存?
struct A
{
int i, j;
std::string str;
private:
float f;
protected:
double d;
};