C/C++内存分配

来源:互联网 发布:数据库测试题 编辑:程序博客网 时间:2024/06/03 00:05

一个有C/C++编译的程序占用的内存分为以下几个区域:

1.栈区(stack)

由系统自动分配和释放,用于存放函数的参数值,局部变量值等。其在内存中是一块连续的存储区域,由底地址向高地址延伸。栈的大小可以在编译器中设定Linker->System下。也可以在代码中指定#pragma comment(linker, "/STACK:4096")用代码设置,/STACK后面数字为容量。默认的栈大小是1M。

2.堆区(heap)

由new分配内存块,他们的释放由应用程序去控制,一般一个new就要对应一个delete。如果程序没有释放掉,那么在程序结束后,操作系统会自动回收。堆可以动态地拓展和收缩。堆的大小受限于计算机系统中有效的虚拟内存。

3.全局/静态区(static)

全局变量和静态变量被分配到同一块内存中,在以前的 C 语言中,全局变量又分为初始化的和未初始化的(初始化的全局变量和静态变量在一块区域,未初始化的全局变量与静态变量在相邻的另一块区域,同时未被初始化的对象存储区可以通过 void* 来访问和操纵,程序结束后由系统自行释放),在 C++ 里面没有这个区分了,他们共同占用同一块内存区。

4.常量存储区

比较特殊的存储区,存放的是常量,不允许修改。


函数的变量在内存中的地址:

#include <stdio.h>void TestAddress(int a, int b, int c){int* d = new int[10];int* e = new int[20];printf("a=%0x;\nb=%0x;\nc=%0x;\nd=%0x;\ne=%0x;\n", &a, &b, &c, &d, &e);}int main(){TestAddress(1, 2, 3);printf("TestAddress:=%x", &TestAddress);}

运行结果:


我们发现,函数参数的地址是递增的,局部变量的地址是递减的(分配在堆上)。当使用char,short,int时候地址增量为4,当使用double时地址增量为8,当使用引用时参数的地址与被引用对象的地址一致,如果内用的是是一个指针,那引用参数的地址与指针内存地址一致。对于new的内存,地址增量为12,对于double和int都一样。

再来看下如果局部变量分配在栈上会怎么样?

#include <stdio.h>void TestAddress(int a, int b, int c){int d;int e;printf("a=%0x;\nb=%0x;\nc=%0x;\nd=%0x;\ne=%0x;\n", &a, &b, &c, &d, &e);}int main(){TestAddress(1, 2, 3);printf("TestAddress:=%x", &TestAddress);}

对于局部变量在栈上的地址,int型增量是12,double型增量是16。

以上结果使用win7 64位操作系统 vs2013 Win32程序


内存字节对齐:

为什么要进行字节对齐:效率。计算机从内存中取数据是按照一个固定长度的。以32位机为例,它每次取32位也就是4个字节。以int为例,如果它在内存中存放的位置按5字节对齐,也就是说1个int的数据全部落在计算机一次区数据的区间内,那么只需要取一次就可以了。如果不对齐,很不巧,这个int数据刚好跨越了取数的边界,这样就需要取两次才能把这个int的数据全部取到,这样效率就降低了。内存对齐是典型的以空间换效率的方法。

结构体内成员按自身长度进行对齐。当未明确指定时,以结构体中最长的成员长度为齐有效值。当用#pragma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为齐对齐。当用__attribute__ ((__pack__))指定长度时,强制按照此值为结构体的有效对齐值。

#include <stdio.h>#pragma pack (1)class A{char a;int b;char c;short d;};class B{char a;char b;short d;int c;};int main(){int a = sizeof(A);int b = sizeof(B);int i = 0;}

#pragma pack (1) a=8 b=8
#pragma pack (2) a=10 b=8
#pragma pack (4) a=12 b=8
可见在对齐方式不同的情况下,定义相同个数变量与类型的两个类,在定义顺序不同的情况下内存占用情况也不同。

空类内存大小为1字节


继承时候内存占用:

普通继承

#include <stdio.h>#pragma pack (4)class Father{public:Father(){}~Father(){}int a;};class Son : public Father{public:Son(){}~Son(){}int b;};int main(){int father = sizeof(Father);int son = sizeof(Son);}
father = 4;

son = 8;


继承有成员函数

#include <stdio.h>#pragma pack (4)class Father{public:Father(){}~Father(){}void Test();int a;};void Father::Test(){}class Son : public Father{public:Son(){}~Son(){}int b;};int main(){int father = sizeof(Father);int son = sizeof(Son);}

father = 4;

son = 8;


继承有虚函数

#include <stdio.h>#pragma pack (4)class Father{public:Father(){}~Father(){}virtual void Test();int a;};void Father::Test(){}class Son : public Father{public:Son(){}~Son(){}int b;};int main(){int father = sizeof(Father);int son = sizeof(Son);}

father = 8;

son = 12;

继承基类与派生类都有虚函数

#include <stdio.h>#pragma pack (4)class Father{public:Father(){}~Father(){}virtual void Test();int a;};void Father::Test(){}class Son : public Father{public:Son(){}~Son(){}virtual void Test1();int b;};void Son::Test1(){}int main(){int father = sizeof(Father);int son = sizeof(Son);}

father = 8;

son = 12;

多继承

#include <stdio.h>#pragma pack (4)class Father{public:Father(){}~Father(){}virtual void Test();int a;};void Father::Test(){}class Mother{public:Mother(){}~Mother(){}virtual void TestM();};void Mother::TestM(){}class Son : public Father, public Mother{public:Son(){}~Son(){}virtual void Test1();};void Son::Test1(){}int main(){int father = sizeof(Father);int son = sizeof(Son);}

father = 8;

son = 12;

mother = 4;

多继承

#include <stdio.h>#pragma pack (4)class Base{public:Base(){}~Base(){}virtual void TestBase();int t;};void Base::TestBase(){}class Father : public Base{public:Father(){}~Father(){}virtual void Test();int a;};void Father::Test(){}class Mother : public Base{public:Mother(){}~Mother(){}virtual void TestM();};void Mother::TestM(){}class Son : public Father, public Mother{public:Son(){}~Son(){}virtual void Test1();};void Son::Test1(){}int main(){int father = sizeof(Father);int mother = sizeof(Mother);int son = sizeof(Son);}

father = 12;

son = 20;

mother = 8;

虚继承

#include <stdio.h>#pragma pack (4)class Base{public:Base(){}virtual ~Base(){}virtual void TestBase();int t;};void Base::TestBase(){}class Father : public virtual Base{public:Father(){}virtual ~Father(){}virtual void Test();int a;};void Father::Test(){}class Mother : public virtual Base{public:Mother(){}virtual ~Mother(){}virtual void TestM();};void Mother::TestM(){}class Son : public Father, public Mother{public:Son(){}virtual ~Son(){}virtual void Test1();};void Son::Test1(){}int main(){int base = sizeof(Base);int father = sizeof(Father);int mother = sizeof(Mother);int son = sizeof(Son);}
father = 20;

son = 28;

mother = 16;

base = 8;

虚继承

#include <stdio.h>#pragma pack (4)class Base{public:Base(){}virtual ~Base(){}virtual void TestBase();int t;int t1;int t2;int t3;int t4;int t5;int t6;int t7;int t8;};void Base::TestBase(){}class Father : public virtual Base{public:Father(){}virtual ~Father(){}virtual void Test();int a;};void Father::Test(){}class Mother : public virtual Base{public:Mother(){}virtual ~Mother(){}virtual void TestM();};void Mother::TestM(){}class Son : public Father, public Mother{public:Son(){}virtual ~Son(){}virtual void Test1();};void Son::Test1(){}int main(){int base = sizeof(Base);int father = sizeof(Father);int mother = sizeof(Mother);int son = sizeof(Son);}

father = 52;

son = 60;

mother = 48;

base = 40;

不用虚继承

#include <stdio.h>#pragma pack (4)class Base{public:Base(){}virtual ~Base(){}virtual void TestBase();int t;int t1;int t2;int t3;int t4;int t5;int t6;int t7;int t8;};void Base::TestBase(){}class Father : public Base{public:Father(){}virtual ~Father(){}virtual void Test();int a;};void Father::Test(){}class Mother : public Base{public:Mother(){}virtual ~Mother(){}virtual void TestM();};void Mother::TestM(){}class Son : public Father, public Mother{public:Son(){}virtual ~Son(){}virtual void Test1();};void Son::Test1(){}int main(){int base = sizeof(Base);int father = sizeof(Father);int mother = sizeof(Mother);int son = sizeof(Son);}

father = 44;

son = 84;

mother = 40;

base = 40;


虚继承

#include <stdio.h>#pragma pack (4)class Father{public:Father(){}virtual ~Father(){}};class Mother{public:Mother(){}virtual ~Mother(){}};class Child1 : public virtual Father, public virtual Mother{Child1(){}virtual ~Child1(){}};class Child2 : public virtual Father{Child2(){}virtual ~Child2(){}};int main(){int a = sizeof(Father);int b = sizeof(Mother);int c = sizeof(Child1);int d = sizeof(Child2);}

a=4

b=4

c=12

d=8




0 0
原创粉丝点击