全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

浅谈C++ 类的实例中 内存分配详解

一个类,有成员变量:静态与非静态之分;而成员函数有三种:静态的、非静态的、虚的。

那么这些个东西在内存中到底是如何分配的呢?

以一个例子来说明:

#include"iostream.h"
class CObject
{
public:
  static int a;
  CObject();
  ~CObject();
  void Fun();
private: 
int m_count; 
int m_index;
};
VoidCObject::Fun(){  cout<<"Fun\n"<<endl;}
CObject::CObject(){  cout<<"Construct!\n";}
CObject::~CObject(){  cout<<"Destruct!\n";}
int CObject::a=1;
void main(){
cout<<"Sizeof(CObject):"<<sizeof(CObject)<<endl; cout<<"CObject::a="<<CObject::a<<endl;
CObject myObject;cout<<"sizeof(myObject):"<<sizeof(myObject)<<endl;
cout<<"sizeof(int)"<<sizeof(int)<<endl;
}

 这是我的一段测试代码, 运行结果是:

 

Sizeof(CObject):8
CObject::a=1
Construct!
sizeof(myObject):8
sizeof(int)4
Destruct!

 我有疑问如下:

(1)C++中,应该是对象才会被分配内存空间吧??为什么CObject内存大小是8,刚好和两个成员变量的大小之和一致!难道还没实例化的时候,类就已经有了内存空间了?

(2)当对象生成了之后,算出的内存大小怎么还是8,函数难道不占用内存空间吗?至少应该放个函数指针在里面的吧?内存是怎样布局的?

(3)静态成员应该是属于类的,怎么类的大小中没有包含静态成员的大小?

下面分别解答如下:

1)Sizeof(CObject)是在编译时就计算了的,一个类定义了,它所占的内存编译器就已经知道了,这时只是得到它占用的大小,并没有分配内存操作 。也可以这样想:编译器肯定知道大小了,这与分配内存空间无关,知道大小了,以后实例化了才能知道要分配多大。

2)类的普通成员、静态成员函数是不占类内存的,至于你说的函数指针在你的类中有虚函数的时候存在一个虚函数表指针,也就是说如果你的类里有虚函数则sizeof(CObject)的值会增加4个字节。

其实类的成员函数实际上与普通的全局函数一样。

只不过编译器在编译的时候,会在成员函数上加一个参数,传入这个对象的指针。

成员函数地址是全局已知的,对象的内存空间里根本无须保存成员函数地址。

对成员函数(非虚函数)的调用在编译时就确定了。

像 myObject.Fun() 这样的调用会被编译成形如 _CObject_Fun( &myObject ) 的样子。

函数是不算到sizeof中的,因为函数是代码,被各个对象共用,跟数据处理方式不同。对象中不必有函数指针,因为对象没必要知道它的各个函数的地址(调用函数的是其他代码而不是该对象)。

类的属性是指类的数据成员,他们是实例化一个对象时就为数据成员分配内存了,而且每个对象的数据成员是对立的,而成员函数是共有的~

静态成员函数与一般成员函数的唯一区别就是没有this指针,因此不能访问非静态数据成员。总之,程序中的所有函数都是位于代码区的。

3)静态成员并不属于某个对象,sizeof取的是对象大小。

知道了上面的时候,就可以改一下来看看:

我也补充一些:

class CObject
{
public:
static int a;
CObject();
~CObject();
void Fun();
private:
double m_count; //这里改成了double
int m_index;
};
这个类用sizeof()测出来的大小是 2*sizeof(double)=16
 
class CObject
{
public:
static int a;
CObject();
~CObject();
void Fun();
private:
char m_count; //这里改成了char
int m_index;
};
大小是2*sizeof(int)=8
class CObject
{
public:
static int a;
CObject();
~CObject();
void Fun();
private:
double m_count; //这里改成了double
int m_index;
char c;
};
sizeof(char)+sizeof(int) <sizeof(double) 所以大小是2*sizeof(double)

其实这里还有一个是内存对齐的问题。

空类大小是1。

另外要注意的一些问题:

先看一个空的类占多少空间?

class Base 
{ 
public: 
  Base(); 
  ~Base(); 
}; 
 class Base {
 public:
Base();
 ~Base();
 };

注意到我这里显示声明了构造跟析构,但是sizeof(Base)的结果是1.

因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含 的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。

而析构函数,跟构造函数这些成员函数,是跟sizeof无关的,也不难理解因为我们的sizeof是针对实例,而普通成员函数,是针对类体的,一个类的成 员函数,多个实例也共用相同的函数指针,所以自然不能归为实例的大小,这在我的另一篇博文有提到。

接着看下面一段代码

class Base 
{ 
public: 
  Base();         
  virtual ~Base();     //每个实例都有虚函数表 
  void set_num(int num)  // 普通成员函数,为各实例公有,不归入sizeof统计 
  { 
    a=num; 
  } 
private: 
  int a;         //占4字节 
  char *p;         //4字节指针 
}; 
  
class Derive:public Base 
{ 
public: 
  Derive():Base(){};   
  ~Derive(){}; 
private: 
  static int st;     //非实例独占 
  int d;           //占4字节 
  char *p;          //4字节指针 
};  
int main() 
{ 
  cout<<sizeof(Base)<<endl; 
  cout<<sizeof(Derive)<<endl; 
  return 0; 
} 
 class Base {
 public:
Base();
virtual ~Base(); //每个实例都有虚函数表
void set_num(int num) { a=num; } //普通成员函数,为各实例公有,不归入sizeof统计
private:
 int a; //占4字节
char *p; //4字节指针
};
class Derive:public Base {
public:
Derive():Base(){};
~Derive(){};
private:
static int st; //非实例独占
int d; //占4字节
char *p; //4字节指针
};
int main() {
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derive)<<endl;
 return 0;
}

结果自然是

12

20

Base类里的int  a;char *p;占8个字节。

而虚析构函数virtual ~Base();的指针占4子字节。

其他成员函数不归入sizeof统计。

Derive类首先要具有Base类的部分,也就是占12字节。

int  d;char *p;占8字节

static int st;不归入sizeof统计

所以一共是20字节。

在考虑在Derive里加一个成员char c;

class Derive:public Base
 
{
 
public:
 
  Derive():Base(){};
 
  ~Derive(){};
 
private:
 
  static int st;
 
  int d;
 
  char *p;
 
  char c;
 
};
 
 class Derive:public Base {
 
public:
 
 Derive():Base(){};
 
 ~Derive(){};
 
private:
 
static int st;
 
 int d;
 
char *p;
 
 char c;
 
};

这个时候,结果就变成了

12

24

一个char c;增加了4字节,说明类的大小也遵守类似class字节对齐,补齐规则。

至此,我们可以归纳以下几个原则:

1.类的大小为类的非静态成员数据的类型大小之和,也就是说静态成员数据不作考虑。

2.普通成员函数与sizeof无关。

以上就是小编为大家带来的浅谈C++ 类的实例中 内存分配详解全部内容了,希望大家多多支持~


# c  # 内存分配  # C++中关键字Struct和Class的区别  # c++中typename和class的区别介绍  # 深入C++中struct与class的区别分析  # C++调试追踪class成员变量的方法  # 浅谈C++内存分配及变长数组的动态分配  # C++动态内存分配(new/new[]和delete/delete[])详解  # 基于C++内存分配、函数调用与返回值的深入分析  # c++ class中成员与分配内存的问题详解  # 都有  # 的是  # 时就  # 改成了  # 里加  # 应该是  # 都是  # 无二  # 这是  # 也就是说  # 知道了  # 我也  # 几个  # 是在  # 还没  # 也会  # 结果是  # 多个  # 也要  # 我有 


相关文章: 创业网站制作流程,创业网站可靠吗?  建站之星免费模板:自助建站系统与智能响应式一键生成  无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?  学校建站服务器如何选型才能满足性能需求?  代购小票制作网站有哪些,购物小票的简要说明?  家庭建站与云服务器建站,如何选择更优?  佛山网站制作系统,佛山企业变更地址网上办理步骤?  如何通过老薛主机一键快速建站?  如何通过宝塔面板实现本地网站访问?  建设网站制作价格,怎样建立自己的公司网站?  如何确保FTP站点访问权限与数据传输安全?  武汉网站制作费用多少,在武汉武昌,建面100平方左右的房子,想装暖气片,费用大概是多少啊?  如何彻底删除建站之星生成的Banner?  如何快速重置建站主机并恢复默认配置?  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  测试制作网站有哪些,测试性取向的权威测试或者网站?  网站制作软件免费下载安装,有哪些免费下载的软件网站?  建站之星如何修改网站生成路径?  如何在IIS中配置站点IP、端口及主机头?  如何通过网站建站时间优化SEO与用户体验?  ,想在网上投简历,哪几个网站比较好?  沈阳制作网站公司排名,沈阳装饰协会官方网站?  实惠建站价格推荐:2025年高性价比自助建站套餐解析  建站主机是什么?如何选择适合的建站主机?  建站10G流量真的够用吗?如何应对访问高峰?  如何有效防御Web建站篡改攻击?  建站主机SSH密钥生成步骤及常见问题解答?  如何获取开源自助建站系统免费下载链接?  导航网站建站方案与优化指南:一站式高效搭建技巧解析  个人摄影网站制作流程,摄影爱好者都去什么网站?  网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?  详解jQuery中基本的动画方法  建站之星2.7模板快速切换与批量管理功能操作指南  公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?  ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  建站之星3.0如何解决常见操作问题?  公司网站的制作公司,企业网站制作基本流程有哪些?  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  成都网站制作公司哪家好,四川省职工服务网是做什么用?  如何基于PHP生成高效IDC网络公司建站源码?  如何正确下载安装西数主机建站助手?  如何选择可靠的免备案建站服务器?  宝华建站服务条款解析:五站合一功能与SEO优化设置指南  建站ABC备案流程中有哪些关键注意事项?  制作销售网站教学视频,销售网站有哪些?  黑客如何通过漏洞一步步攻陷网站服务器?  临沂网站制作企业,临沂第三中学官方网站?  制作国外网站的软件,国外有哪些比较优质的网站推荐?  如何用PHP快速搭建CMS系统? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。