C++ 内存布局:内存布局基础
2016-06-24 00:13
435 查看
1、在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆:就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区:就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。
2、C++中考虑内存布局,主要是针对类内部的内存分布。类的内存分布涉及的内容比较多,我们先从最简单的来看。
一、一个简单的类,没有继承,没有虚函数表
第一个CBase 的大小是1,虽然CBase只有一个构造函数,但是这个1并不是构造函数所占据的内存空间。构造函数所占据的内存空间在全局区。使用sizeof(CBase)所得到的大小,是编译器优化的结果。
第二个CBaseClass 的大小是4,这是因为CBaseClass 的内部含有一个int型的变量,该变量占据4字节,所以输出的值便是4字节。CBaseClass中那么多的函数,不论是public还是private,均处于全局区。
上面这幅图是在VS2013 X86(Win32 Debug)的条件下进行编译的,得到上面的内存布局图,我们可以清除的看到每个类中的成员分布。
二、简单的继承
在上面的代码的基础上进行扩展,得到如下的代码
代码输出的内容如下:
我们可以看到baseClass 的大小任然是4,这也在一定的层次上说明了继承不会影响基类的内存分布。derivedClass 大小是12,这是因为除了其本身的两个int型的成员变量外,还有基类的成员变量。虽然基类的成员变量是私有的,derivedClass对这一私有成员没有访问权限,但是从继承体系上来看,派生类继承了基类的所有的内部关系,所以在计算派生类的大小时,需要考虑基类的大小。
上图展示出了基类和派生类的内存分布关系
三、多继承
继续修改上面的代码,得到如下的内容
上面代码的输出如下:
其内存分布如下图所示:
从其内存分布来看,可以很明了的知道多继承CMultiDerivedClass的大小为28,因为上面有7个变量。多继承具体的关系如下图所示:
多继承内存分布总是从第一个继承的类的成员开始分布,然后是第二个,第三个....
在考虑类的内存布局时,同样需要考虑内存对齐等问题。这一方面,在这不多说,网上的资料很多。
栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆:就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区:就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。
2、C++中考虑内存布局,主要是针对类内部的内存分布。类的内存分布涉及的内容比较多,我们先从最简单的来看。
一、一个简单的类,没有继承,没有虚函数表
#include <iostream> using namespace std; class CBase { //public public: CBase() { } }; class CBaseClass { //private members private: int nCount; //public members public: //private member funcs private: CBaseClass(const CBaseClass &base) { } CBaseClass &operator = (const CBaseClass& base) { return *this; } //public members public: CBaseClass(int count = 0) { nCount = count; } ~CBaseClass() { } }; void main() { CBase base; cout << "base Size" << sizeof(base) << endl; CBaseClass baseClass(10); cout << "baseClass Size" << sizeof(baseClass) << endl; cin.get(); }上面代码的输出如下所示:
第一个CBase 的大小是1,虽然CBase只有一个构造函数,但是这个1并不是构造函数所占据的内存空间。构造函数所占据的内存空间在全局区。使用sizeof(CBase)所得到的大小,是编译器优化的结果。
第二个CBaseClass 的大小是4,这是因为CBaseClass 的内部含有一个int型的变量,该变量占据4字节,所以输出的值便是4字节。CBaseClass中那么多的函数,不论是public还是private,均处于全局区。
上面这幅图是在VS2013 X86(Win32 Debug)的条件下进行编译的,得到上面的内存布局图,我们可以清除的看到每个类中的成员分布。
二、简单的继承
在上面的代码的基础上进行扩展,得到如下的代码
#include <iostream> using namespace std; class CBase { //public public: CBase() { } }; class CBaseClass { //private members private: int nCount; //public members public: //private member funcs private: CBaseClass(const CBaseClass &base) { } CBaseClass &operator = (const CBaseClass& base) { return *this; } //public members public: CBaseClass(int count = 0) { nCount = count; } ~CBaseClass() { } }; class CDerivedClass : public CBaseClass { //private members: private: int nDeriveCount; //public members public: int nCurrentNum; //private member funcs private: CDerivedClass(const CDerivedClass& derived) { } CDerivedClass & operator = (const CDerivedClass &derived) { return *this; } //public member funcs public: CDerivedClass(int nDerived = 0) { nDeriveCount = nDerived; nCurrentNum = 0; } }; void main() { CBase base; cout << "base Size:" << sizeof(base) << endl; CBaseClass baseClass(10); cout << "baseClass Size:" << sizeof(baseClass) << endl; CDerivedClass derivedClass(12); cout << "derivedClass Size:" << sizeof(derivedClass) << endl; cin.get(); }
代码输出的内容如下:
我们可以看到baseClass 的大小任然是4,这也在一定的层次上说明了继承不会影响基类的内存分布。derivedClass 大小是12,这是因为除了其本身的两个int型的成员变量外,还有基类的成员变量。虽然基类的成员变量是私有的,derivedClass对这一私有成员没有访问权限,但是从继承体系上来看,派生类继承了基类的所有的内部关系,所以在计算派生类的大小时,需要考虑基类的大小。
上图展示出了基类和派生类的内存分布关系
三、多继承
继续修改上面的代码,得到如下的内容
#include <iostream> using namespace std; class CBase { //public public: CBase() { } }; class CBaseClass { //private members private: int nCount; //public members public: //private member funcs private: CBaseClass(const CBaseClass &base) { } CBaseClass &operator = (const CBaseClass& base) { return *this; } //public members public: CBaseClass(int count = 0) { nCount = count; } ~CBaseClass() { } }; class CBaseClassNew { //private members private: int nCount; //public members public: int nNewCount; //private member funcs private: CBaseClassNew(const CBaseClassNew &base) { } CBaseClassNew &operator = (const CBaseClassNew& base) { return *this; } //public members public: CBaseClassNew(int count = 0) { nCount = count; } ~CBaseClassNew() { } }; class CDerivedClass : public CBaseClass { //private members: private: int nDeriveCount; //public members public: int nCurrentNum; //private member funcs private: CDerivedClass(const CDerivedClass& derived) { } CDerivedClass & operator = (const CDerivedClass &derived) { return *this; } //public member funcs public: CDerivedClass(int nDerived = 0) { nDeriveCount = nDerived; nCurrentNum = 0; } }; class CMultiDerivedClass :public CDerivedClass, public CBaseClassNew { //private members private: int nMultiCount; //public members public: int nNewMultiCount; //private member funcs private: CMultiDerivedClass(const CMultiDerivedClass& derived) { } CMultiDerivedClass & operator = (const CMultiDerivedClass &derived) { return *this; } //public member funcs public: CMultiDerivedClass(int nCount) { nMultiCount = nCount; nNewMultiCount = 0; } ~CMultiDerivedClass() { } }; void main() { CBase base; cout << "base Size:" << sizeof(base) << endl; CBaseClass baseClass(10); cout << "baseClass Size:" << sizeof(baseClass) << endl; CDerivedClass derivedClass(12); cout << "derivedClass Size:" << sizeof(derivedClass) << endl; CMultiDerivedClass multiDerivedClass(5); cout << "multiDerivedClass Size:" << sizeof(multiDerivedClass) << endl; cin.get(); }
上面代码的输出如下:
其内存分布如下图所示:
从其内存分布来看,可以很明了的知道多继承CMultiDerivedClass的大小为28,因为上面有7个变量。多继承具体的关系如下图所示:
多继承内存分布总是从第一个继承的类的成员开始分布,然后是第二个,第三个....
在考虑类的内存布局时,同样需要考虑内存对齐等问题。这一方面,在这不多说,网上的资料很多。
相关文章推荐
- C++与C有什么不同
- Algorithm: STD C++文件夹内容读取.
- C/C++语言中“:”的使用方法
- C++基本数据表达式
- c++杂乱知识
- Hough变换——直线检测(投票方法实现)
- Ubuntu 14.04下安装eclipse搭建C++开发环境
- 字节对齐分析
- C++之类的组合(聚合)
- C++ 类的抽象初练
- 【C++编译】gcc的-l参数和-L参数
- 选择排序
- 使用c语言实现一个简单的易语言
- C++ 类
- C++走向远洋——68(十六周、文件)
- 处理C++源代码的程序
- 查漏补缺——C/C++基本类型
- ubuntu下C++两种方法解析json
- C,D,I 的C++实现
- c语言学习笔记35之calloc