1. 普通对象模型

对象是如何在内存中布局的?

成员 存放位置 访问范围
非静态数据成员 每一个对象体内 为该对象专有
静态数据成员 程序的静态存储区内,只有一份实体 为该类所有对象共享
成员函数(静态/非静态) 程序的代码段中,只有一份实体 为该类所有对象共享
类类嵌套的各种类型(typedef、class、struct、enum等) 与放在类外面定义的类型除了定义域之外没有本质区别 遵循类内部的访问规则

因此,构成对象本身的只有数据,类的成员函数不属于任何一个对象。非静态成员函数与对象之间的关系是通过this指针绑定的。

2. 增加继承和虚函数的类的对象模型

派生类的对象是如何在内存中布局的?

成员 规则
继承自基类的非静态数据成员 作为对象自己专用的数据
继承自基类的非静态成员函数 作为类的成员函数一样访问
虚函数(继承的或者新增的) 所有虚函数的地址都存放在vtable里
多态类每一个对象中的vptr 函数指针的指针,指向所属类的vtable
继承自基类的vptr 继承和重用该vptr
多重继承的多个分支 每个分支都继承一个vptr并生成一个对应的vtable

vptr在派生类对象中的相对位置不会随着继承的层次改变而改变,一般编译器会将vptr放在所有数据成员的最前面。

为了支持RTTI,编译器会为每一个多态类创建一个type_info对象,并把其地址保存在该类vtable中的第一个位置。

3. vtable中虚函数指针的排列顺序

  1. 如果虚函数是第一次出现,则把它的函数地址指针依次插入到vtable的尾部。
  2. 如果派生类改写了基类的虚函数,则这个函数的地址在派生类vtable中的位置与其在基类vtable中的位置一直,而与其在派生类中的声明位置无关。也就是说一旦虚函数指针在vtable的位置确定,则它的位置就不会因为继承层次的改变而改变。
  3. 派生类没有改写的基类虚函数被继承,位置与原先在vtable中的位置相同。

C++对象的内存模型的更多相关文章

  1. Java对象的内存模型(一)

    前言 新人一枚,刚刚入门编程不久,各方面都在学习当中,博文有什么错误的地方,希望我们可以多多交流! 最近,在开发App后台过程中,需要将项目部署到云服务器上.而云服务器的内存大小却只有1G.要如何做到 ...

  2. C++学习笔记----2.4 C++对象的内存模型

    转载自:http://c.biancheng.NET/cpp/biancheng/view/2995.html点击打开链接 当对象被创建时,编译器会为每个对象分配内存空间,包括成员变量和成员函数. 直 ...

  3. 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响

    首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...

  4. 对C++对象内存模型造成的影响(类/对象的大小)

    首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...

  5. String的内存模型,为什么String被设计成不可变的

    String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么要设计成不可变呢? 前言 关于String,收集一波基础,来源 ...

  6. C++对象的内存分布和虚函数表

    c++中一个类中无非有四种成员:静态数据成员和非静态数据成员,静态函数和非静态函数. 1.非静态数据成员被放在每一个对象体内作为对象专有的数据成员.    2.静态数据成员被提取出来放在程序的静态数据 ...

  7. Java对象的内存(一)

    前言 新人一枚,刚刚入门编程不久,各方面都在学习当中,博文有什么错误的地方,希望我们可以多多交流! 最近,在开发App后台过程中,需要将项目部署到云服务器上.而云服务器的内存大小却只有1G.要如何做到 ...

  8. (转)JavaScript内存模型

    JavaScript对象内存模型 转自:http://blog.csdn.net/u010425776/article/details/53617292  推荐-JavaScript作用域链内存模型: ...

  9. C++/C#中堆栈、对象内存模型、深浅拷贝、Array.Clone方法

    转载自:http://blog.csdn.net/jarvischu/article/details/6425534 目录 1.      C++/C#中对象内存模型................. ...

随机推荐

  1. BZOJ 4278 [ONTAK2015]Tasowanie (后缀数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4278 题解: 居然把后缀数组写成n^2的..我真厉害.. 想了无数种方法,最后发现就是 ...

  2. 协程,greenlet原生协程库, gevent库

    协程简介 协程(coroutine),又称为微线程,纤程,是一种用户级的轻量级线程.协程拥有自己的寄存器上下文和栈. 协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来时,恢复之前保存的上下文 ...

  3. [cogs731] [网络流24题#6] 最长递增子序列 [网络流,最大流]

    [转hzwer]第一问是LIS,动态规划求解,第二问和第三问用网络最大流解决.首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K.1.把序列每位i拆成两个点< ...

  4. 用sqlldr导入csv文件

    1.新建文件test.ctl,内容如下 load dataCHARACTERSET 'UTF16' \*指定编码格式,很重要*\ infile 'vodall.csv' append into tab ...

  5. 在Centos安装oracle_11gR2进度68%"Error in invoking target mkldflags ntcontab.o nnfgt.o of makefile..”

    http://www.xwood.net/_site_domain_/_root/5870/5874/t_c265367.html

  6. 递归算法详细分析->C

    C通过运行时堆栈支持递归函数的实现.递归函数就是直接或间接调用自身的函数.     许多教科书都把计算机阶乘和菲波那契数列用来说明递归,非常不幸我们可爱的著名的老潭老师的<C语言程序设计> ...

  7. N天学习一个linux命令之xargs

    用途 标准输入流读取参数(空格或者换行符分隔),传递给需要执行的命令 用法 xargs [options] [command [initial-arguments]] 常用选项 --arg-file= ...

  8. 优化实例- not in 和 not exists

    客户运行一个SQL,非常慢.于是进行了一下改写.速度飞快,首先看一下原来的SQL. original sql SQL> explain plan for 2 select count(*) fr ...

  9. Error-MySQL:2005 - Unknown MySQL server host 'localhost'(0)

    ylbtech-Error-MySQL:2005 - Unknown MySQL server host 'localhost'(0) 1.返回顶部 1. 今天在外面开navicat for mysq ...

  10. 第14课 SourceTree程序操作介绍

    http://www.atlassian.com/software/sourcetree/overview https://www.microsoft.com/net/framework/versio ...