本文仅代表博主自己对C++内存对象模型的一点理解,如果文中有

理解偏差和不准确的地方,希望各位大大提出,我好及时改正。

本博文只对博主自己负责,不对任何人负责。

就如《深度探索C++对象模型》一书中介绍的C++的封装并没有给C++带来过多的开销。然而面向对象的编程方法却给广大的编程者提供了一种

更为开阔的编程思路。

好,我们主要看看前面一句。开销是什么,这里的开销主要指C++类所占内存的空间。首先,我们看这样一个例子,我们定义一个结构体和类,结

构体和类中含有相同的数据成员。除此之外再无其他。我们看看这个结构体和类的大小是多少:

 #include <iostream>
using namespace std; struct A
{
int a;
int b;
int c;
}; class B
{
int a;
int b;
int c;
}; int main()
{
cout<<"sizeof(A)="<<sizeof(A)<<endl;
cout<<"sizeof(B)="<<sizeof(B)<<endl;
return ;
}

结果:

看来只要数据成员相同,那么就算声明为类,也不会带来额外的内存开销。

现在我们再看一个例子,我们让类B更加复杂一下,我们添加一个静态成员变量和,一个静态成员函数,一个非静态成员函数,一个

虚函数:我们再看看这个例子的结果将是什么样的结果:

 #include <iostream>
using namespace std; struct A
{
int a;
int b;
int c;
}; class B
{
private:
int a;
int b;
int c;
static int d; public:
static void fun1()
{
cout<<"This is a static fun1."<<endl;
} void fun2()
{
cout<<"This is ordinary fun2."<<endl;
} virtual void fun3()
{
cout<<"This is a virtual fun3."<<endl;
}
}; int main()
{
cout<<"sizeof(A)="<<sizeof(A)<<endl;
cout<<"sizeof(B)="<<sizeof(B)<<endl;
return ;
}

结果:

在这里我们增加了一个静态数据成员d,一个静态成员函数fun1,非静态的成员函数fun2一个虚函数fun3.不难发现就类的代码规模

来说,的确增加了不少,然而结果仅仅比之前增加了四个字节的开销。《深度探索C++对象模型》中有这样一句话说C++封装所带来

的开销主要来源于虚函数。

那么我们可以先看看结构体A的内存分布:可以产生结构体A的一个对象:

     A *a;
a=new A;

对象a的内存结构如下:

显然a中有三个整型数据元素a,b,c刚好12个字节

现在我们看看类B的内存分布

可以产生类B的一个对象:

     B *b;
b=new B;

对象B的内存结构如下:

可以看到尽管类B封装的很多的内容,但是较之A而言仅仅多了一个__vfptr,我们不禁回忆起前面的一句话,C++的封装的开销主要来自于虚

函数。其实如果对C++有一定了解的同学都不难猜出,这个ptr其实就是一个虚表指针。正因为这个虚表指针给封装带来了额外的4个字节的开销。

那么虚表指针是什么呢,虚表指针其实就是指向虚函数表的一个指针。当一个类中有虚函数的时候,类会自动生成一个指针,该指针保存的是该类

中第一个虚函数的地址。所以就算有多个虚函数仍然只需要保存一个虚表指针,然后通过这个指针逐个遍历就可以取得各个虚函数的地址。然而关于

虚函数在C++中功能特性我们留待下次一起学习了。

这下一目了然了吧。

 

那么我们可以总结一下影响类的内存开销主要有以下几个方面:

1.非静态的数据成员

2.虚函数表指针

3.当然既然类也是要考虑内存对齐的。

还有几点需要注意:

1.类的静态数据成员存储在全局变量区,不带来C++内存开销,该静态数据成员属于整个类的不属于具体某个对象,其初始化要在类外进行。

2.类的静态成员函数是属于整个类的,不属于某个对象,不会带来内存开销。注意类的静态成员函数中不能调用非静态的成员变量。

3.类的普通成员函数始终在程序的代码区中保存一份,不带来内存开销。

 

 

最后再通过一张图片只管展示结构体A和类B的内存布局:

C++对象模型浅析的更多相关文章

  1. 浅析MVC模式与三层架构的区别

    浅析MVC模式与三层架构的区别 三层架构和MVC是有明显区别的,MVC应该是表现模式(三个加起来以后才是三层架构中的UI层).三层架构(3-tier application) 通常意义上的三层架构就是 ...

  2. 深入理解多线程(二)—— Java的对象模型

    上一篇文章中简单介绍过synchronized关键字的方式,其中,同步代码块使用monitorenter和monitorexit两个指令实现,同步方法使用ACC_SYNCHRONIZED标记符实现.后 ...

  3. 浅析Apache/Tomcat/JBOSS/Nginx之区别

    浅析Apache/Tomcat/JBOSS/Nginx服务器之区别 一.Apache和Tomcat的区别 Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上, ...

  4. 浅析C#组件编程中的一些小细节

    控件与组件的区别(Control&Component的区别) 作者:作者不详  发布日期:2011-06-30 12:08:41 控件与组件的区别(Control&Component的 ...

  5. 【转帖】Flink 核心技术浅析(整理版)

    Flink 核心技术浅析(整理版) https://www.cnblogs.com/swordfall/p/10612404.html 分类: Flink undefined 1. Flink简介 A ...

  6. protobuf 协议浅析

    目录 Protobuf 协议浅析 1. Protobuf 介绍 1.1 Protobuf 基本概念 1.2 Protobuf 的优点 1.3 Protobuf, JSON, XML 的区别 2. Pr ...

  7. kubernetes VS OpenShift浅析

    Kubernetes vs OpenShift浅析 古语有云:"知彼知己,百战不殆.不知彼而知己,一胜一负.不知彼,不知己,每战必殆." 这句话同样也适用于技术体系.无论我们在落地 ...

  8. SQL Server on Linux 理由浅析

    SQL Server on Linux 理由浅析 今天的爆炸性新闻<SQL Server on Linux>基本上在各大科技媒体上刷屏了 大家看到这个新闻都觉得非常震精,而美股,今天微软开 ...

  9. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

随机推荐

  1. 返回本机的mac物理路径

     /// <summary>         ///    返回本机的mac物理路径         /// </summary>         /// <return ...

  2. Fancy

    Fancy 在欢喜您可以轻易发现并购买由全球最具品味的社区为您挑选的精美商品.

  3. Python 异步IO、IO多路复用

    事件驱动模型 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  4. Udp实现简单的聊天程序

    在<UDP通讯协议>这篇文章中,简单的说明了Udp协议特征及如何Udp协议传输数据 这里将用Udp协议技术,编写一个简单的聊天程序: //发送端: package com.shindo.j ...

  5. android 推断Apk是否签名和 签名是否一致

    推断Apk是否签名 用命令:jarsigner -verify -verbose -certs <apk文件> 假设有Android Debug字樣就是debug 假设已经签名: [证书的 ...

  6. 利用Unicorn和Idaemu辅助解决Geekpwn SecretCode

    在前面的些文章里,我提到了怎么交叉编译Unicorn-engine,以及在windows上使用Unicorn python bindings进行分析程序.这一次我介绍下如何使用Unicorn-engi ...

  7. Apache-rhel5.8环境下编译安装

    Apache安装过程 Step 1:安装包gcc或gcc-c++# yum install gcc#yum install gcc-c++ Step 2:安装包APR和APR-Utilapr-1.4. ...

  8. ie6+7+8等对background-color:rgba(),background-img渐变的兼容

    一,ie8兼容rgba()的解决办法 今天遇到了一个问题,要在一个页面中设置一个半透明的白色div.这个貌似不是难题,只需要给这个div设置如下的属性即可: background: rgba(255, ...

  9. css之浏览器初始化方案

    HTML, body, div, h1, h2, h3, h4, h5, h6, ul, ol, dl, li, dt, dd, p, blockquote,pre, form, fieldset, ...

  10. J2EE 中 The function valueOf must be used with a prefix when a default namespace is not specified 错误

    jsp页面中,JSTL El表达式字符串比较常用方法 fn:contains 判断字符串是否包含另外一个字符串 <c:if test="${fn:contains(name, sear ...