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
- c/C++内存分配
- C内存分配
- C语言内存分配
- C/C++内存分配
- C/C++内存分配
- c内存分配
- C/C++内存分配
- C程序内存分配
- c 内存分配
- C语言内存分配
- C内存分配
- C的内存分配
- c语言内存分配
- c内存分配
- C语言-内存分配
- C语言内存分配
- c程序内存分配
- C/C++内存分配
- zookeeper原理
- Linux学习5之查找文件中的某个字符串并返回所在行号
- 认识Python
- 多线程安全问题
- java内存相关知识
- C/C++内存分配
- PythonChallenge Mission 17
- AppWidget运用实例
- 哈希表详解
- network2
- IP动态选路和最短路算法
- leetcode 18.4Sum
- LeakCanary源码分析
- vector 释放内存 swap