c++中,类的成员变量,以及成员函数,在类中的分布是怎么样的。

飞翔的薄荷 2015-09-25 09:29:43
class A
{
int a;
int b;
virtual int fun();
};

在类A中,a变量的地址 偏移a变量类型大小是否一定得到b变量的地址。然后b变量的地址偏移b变量类型大小后,得到fun的地址。
上面这样的结果,是否有c++标准的支持。
...全文
257 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2015-09-26
  • 打赏
  • 举报
回复
简单地说, 成员函数,不在对象内, 静态数据成员,不在对象内 可以优化的成员变量,也可能不在对象内 另外对象中,可能会塞入一些额外的,程序运行所必需的东西。如虚函数表指针 除此之外,数据对齐,可能会花费一些内存空间。 因为要和C的struct 兼容 struct 和class 又采用大致相同的内存布局策略 所以,类对象的内存中的,非静态成员变量,大致依照定义顺序排列。
lm_whales 2015-09-26
  • 打赏
  • 举报
回复
类的内存布局,C++标准没有规定 因此是多种多样的可能性都有 还跟数据对齐相关 因此没有统一的模式 但是你只是大概能知道,一般编译系统会采用哪些措施,安排每个成员的位置 但有些东西,是可以知道的 例如成员函数本身,不占用对象的内存 虚函数可能只是虚函数表中的一个指针的位置 一份虚函数表可能会占有一个指针的内存
fefe82 2015-09-25
  • 打赏
  • 举报
回复
引用 10 楼 ml232528 的回复:
[quote=引用 8 楼 fefe82 的回复:] 只要求访问控制相同的成员变量,后定义的地址高于先定义的。对是否连续没有要求。对不同访问控制的如何分布没有要求。 在 C++ 里, struct 和 class 没有除了默认访问控制不一样,没有其它区别。
这是把struct当成类来说的。如果struct里只有基础类型的变量(c语言里的结构体)。就不一样了,struct定义的东西可以使用mem开头的那些函数,class则不行。 [/quote] 这种东西在 C++ 里叫 standard-layout class 。他需要满足的条件很多,但是与他用 struct 或 class 定义无关。
lm_whales 2015-09-25
  • 打赏
  • 举报
回复
虚函数,有个虚函数表指针,指向对应的虚函数表,虚函数表里面有虚函数, 一个类的对象, 可能不止一个虚表指针,也可能不止有一份虚表 虚拟继承,有个顶层类对象指针,和唯一一份顶层对象。 另外,虚表里面,可能还包含类本身的信息。 其他,还有非静态数据成员 引用可能存储为指针,也可能是别的什么。 类的静态常量不占用对象的内存 类的静态成员数据也是。 类的静态函数,以及非虚成员函数,不占用对象的内存 虚函数指针,只是占用虚表中的一个位置,而不必每个函数。都存储在对象中。 类非静态常量,一般都占有内存。 enum 常量,不占内存 typedef 的类型,叶不占有内存 类的 非静态成员变(常量)量, 通常按照定义的顺序排列 , 并且按照某种规律对齐处理 类的方法(成员函数),只是一个函数代码,不一定会,占用内存。
www_adintr_com 2015-09-25
  • 打赏
  • 举报
回复
引用 9 楼 adlay 的回复:
你知道它怎么实现的只有益处没有害处,只要你不去写依赖这些实现来工作的代码就行。 现实中你总会遇到各种扩展,各种和标准不兼容的现象,像这个通过分析各种编译器实现来完成的 delegate 就会比用标准 C++ 去实现高效得多。
链接发掉了: http://www.adintr.com/mytranslate/fastdelegate.html
飞翔的薄荷 2015-09-25
  • 打赏
  • 举报
回复
引用 8 楼 fefe82 的回复:
只要求访问控制相同的成员变量,后定义的地址高于先定义的。对是否连续没有要求。对不同访问控制的如何分布没有要求。 在 C++ 里, struct 和 class 没有除了默认访问控制不一样,没有其它区别。
这是把struct当成类来说的。如果struct里只有基础类型的变量(c语言里的结构体)。就不一样了,struct定义的东西可以使用mem开头的那些函数,class则不行。
www_adintr_com 2015-09-25
  • 打赏
  • 举报
回复
引用 7 楼 ml232528 的回复:
[quote=引用 4 楼 yshuise 的回复:] 同编译器实现有关。
引用 5 楼 adlay 的回复:
C++ 标准似乎从来都不会规定实现方法... 虚函数表 这个几乎是所有 C++ 编译期都这么实现的,参考《深度探索C++对象模型》
如果只是编译器实现,还是不要把它当成正确的吧。貌似只有结构体,可以把这些结论当成正确的来使用吧。c++毕竟要兼容c。[/quote] 你知道它怎么实现的只有益处没有害处,只要你不去写依赖这些实现来工作的代码就行。 现实中你总会遇到各种扩展,各种和标准不兼容的现象,像这个通过分析各种编译器实现来完成的 delegate 就会比用标准 C++ 去实现高效得多。
fefe82 2015-09-25
  • 打赏
  • 举报
回复
9.3 Class members 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++ 里, struct 和 class 没有除了默认访问控制不一样,没有其它区别。
飞翔的薄荷 2015-09-25
  • 打赏
  • 举报
回复
引用 4 楼 yshuise 的回复:
同编译器实现有关。
引用 5 楼 adlay 的回复:
C++ 标准似乎从来都不会规定实现方法... 虚函数表 这个几乎是所有 C++ 编译期都这么实现的,参考《深度探索C++对象模型》
如果只是编译器实现,还是不要把它当成正确的吧。貌似只有结构体,可以把这些结论当成正确的来使用吧。c++毕竟要兼容c。
www_adintr_com 2015-09-25
  • 打赏
  • 举报
回复
引用 5 楼 adlay 的回复:
[quote=引用 2 楼 ml232528 的回复:] [quote=引用 1 楼 adlay 的回复:] a变量的地址 偏移a变量类型大小是否一定得到b变量的地址 是的 C++ 保证在同一个 private/public/protected 下的变量的顺序和定义的时候一致。 然后b变量的地址偏移b变量类型大小后,得到fun的地址 错的 函数的地址如果不是虚函数,是不会放在对象中的 如果是虚函数,则会把这个类的所有虚函数放到一个表中,这个表是一个类才有一份的,对象中只有一个指针指向这个表。 不管虚函数有多少个,在对象中也只需要占用 4 个字节(没有多继承的情况下)。 而这个虚表的指针和函数出现的位置没有关系,有编译期决定放对象的开头或其他位置。
这个是c++标准规定么?还是说是大部分编译器实现方案? [/quote] C++ 标准似乎从来都不会规定实现方法... 虚函数表 这个几乎是所有 C++ 编译期都这么实现的,参考《深度探索C++对象模型》[/quote] 编译期-》编译器
www_adintr_com 2015-09-25
  • 打赏
  • 举报
回复
引用 2 楼 ml232528 的回复:
[quote=引用 1 楼 adlay 的回复:] a变量的地址 偏移a变量类型大小是否一定得到b变量的地址 是的 C++ 保证在同一个 private/public/protected 下的变量的顺序和定义的时候一致。 然后b变量的地址偏移b变量类型大小后,得到fun的地址 错的 函数的地址如果不是虚函数,是不会放在对象中的 如果是虚函数,则会把这个类的所有虚函数放到一个表中,这个表是一个类才有一份的,对象中只有一个指针指向这个表。 不管虚函数有多少个,在对象中也只需要占用 4 个字节(没有多继承的情况下)。 而这个虚表的指针和函数出现的位置没有关系,有编译期决定放对象的开头或其他位置。
这个是c++标准规定么?还是说是大部分编译器实现方案? [/quote] C++ 标准似乎从来都不会规定实现方法... 虚函数表 这个几乎是所有 C++ 编译期都这么实现的,参考《深度探索C++对象模型》
yshuise 2015-09-25
  • 打赏
  • 举报
回复
同编译器实现有关。
飞翔的薄荷 2015-09-25
  • 打赏
  • 举报
回复
大部分c++的书,并没有提到这个,如果是编译器实现,那么不能认为它是正确的。除非c++标准规定。
飞翔的薄荷 2015-09-25
  • 打赏
  • 举报
回复
引用 1 楼 adlay 的回复:
a变量的地址 偏移a变量类型大小是否一定得到b变量的地址 是的 C++ 保证在同一个 private/public/protected 下的变量的顺序和定义的时候一致。 然后b变量的地址偏移b变量类型大小后,得到fun的地址 错的 函数的地址如果不是虚函数,是不会放在对象中的 如果是虚函数,则会把这个类的所有虚函数放到一个表中,这个表是一个类才有一份的,对象中只有一个指针指向这个表。 不管虚函数有多少个,在对象中也只需要占用 4 个字节(没有多继承的情况下)。 而这个虚表的指针和函数出现的位置没有关系,有编译期决定放对象的开头或其他位置。
这个是c++标准规定么?还是说是大部分编译器实现方案?
www_adintr_com 2015-09-25
  • 打赏
  • 举报
回复
a变量的地址 偏移a变量类型大小是否一定得到b变量的地址 是的 C++ 保证在同一个 private/public/protected 下的变量的顺序和定义的时候一致。 然后b变量的地址偏移b变量类型大小后,得到fun的地址 错的 函数的地址如果不是虚函数,是不会放在对象中的 如果是虚函数,则会把这个类的所有虚函数放到一个表中,这个表是一个类才有一份的,对象中只有一个指针指向这个表。 不管虚函数有多少个,在对象中也只需要占用 4 个字节(没有多继承的情况下)。 而这个虚表的指针和函数出现的位置没有关系,有编译期决定放对象的开头或其他位置。

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧