转自:http://blog.csdn.net/yingjiebohe/article/details/7293906
算是在前人的基础上改动的吧。
只知其表,不知其理。这是我们衡量一个人专业知识是否有深度的基本法则?作为初来乍到的程序猿来说,内存分析是我们编写速度快、效率高的代码必不可少的知识。如果自己编写的代码在内存的分配一无所知,我想这样的程序让你去优化,应该是无从下手的。
下面就我学习到的那点内存知识和大家分享一下,如有理解错误的地方,还请各位拍砖。
(一)先解释一下静态内存分析与动态内存分析
下面以C++为例解释:程序中用于存储数据的变量和数组等实体在使用前都必须通过说明语句进行定义。C++编译器将根据这额说明语句了解他们所需存储空间的大小,并预先为其分配适当的内存空间。也就是说,这些变量或数组在内存中所占据的空间大小必须在编译时(即程序运行前)确定下来的,这种内存分配方式称为“静态存储分配”
很多情况下,程序中所需的内存数量只有等到运行时刻才能确定下来。例如,需要在程序运行期间根据用户提供的输入信息决定分配存储空间的大小。这时就应使用“动态存储分配”方式申请获得指定大小的内存空间;当动态分配的内存空间闲置不用时通用有必要对其进行释放。动态存储分配功能在C++ 中是通过new和delete运算符来实现。
(二)五大内存分区
在C++中,内存分成5个去,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区
栈:就是那些由编译器在需要的时候分配的,在不需要的时候自动清除的变量的存储区。也就是说那些静态存储分配的局部变量都在这里。
堆:动态存储分配的,由new分配的内存块,它们的释放编译器不去管,而是由应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区:就是那些由malloc等分配的内存块,它和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区:全局变量和静态变量被分到同一块内存中。
常量存储区:这是一块比较特殊的存储区,它们里面存放的是常量,不允许修改。如果非要修改在C++中也可以利用const进行修改。
(三)变量内存分析
在C++中变量的存储有四种形式:
1.auto变量:用关键字auto声明的局部变量称为自动变量。在变量定义时,如果不显示标明存储类别,则系统自动按auto变量处理。auto变量所占用存储空间的分配和释放工作将由系统自动完成。
也就是 int num;等价于auto int num;
2.register变量:用关键字register声明的局部变量称为寄存器变量,声明寄存器变量时,关键字register的作用只能是建议(而不是强制)系统使用寄存器,原因是寄存器虽然存取速度快,但空间有限,当寄存器不够用时,该变量仍然按自动变量处理。
这个可以好好利用
3.static变量:用关键字static声明的变量称为静态变量。任何静态变量的生存期将延续到整个程序的终止。与全局变量一样,为静态变量分配的存储空间在整个程序运行过程中不再被释放;如果静态变量未被赋初值,系统将自动为其赋初值为0;由静态变量我们能想到代码中定义的静态方法是,一旦方法定义为静态,内存就会为该方法分配一定的空间并将持续保存,如果过多的使用静态方法或者是静态变量也就造成了全局/静态存储区空间变得拮据。这也就是为什么在我们平日的编程中都是使用实例化对象(new)去调用该方法。
4.extern变量:用关键字extern声明的变量称为外部变量。变量一旦被声明为外部变量,系统就不必像一般变量那样为其分配内存。
(四)堆和栈的区别
管理方式不同:栈是由编译器自动管理的。堆的释放工作是由程序员来控制的(delete),容易忽略。
空间大小不同:栈,一般都是有一定的空间大小。堆内存几乎是不受限制的。
碎片的产生:堆,频繁的new/delete势必会造成内存空间的不连续,造成大量的碎片空间,程序效率降低。栈,不会存在这个问题,栈是先进后出的队列,所以永远不可能在内存块中间出现碎片。
这个告诫我们在new过的实例用完之后应该立即释放,这样保证碎片不太多。
分配方式不同:堆是动态分配的,没有静态分配的堆。栈有两种分配方式:静态和动态,静态分配时编译器自己完成的(局部变量)动态分配是由alloca函数进行分配。
记住new、alloca和malloc之间的区别:
(1)new是分配到堆空间里面的,使用delete对其进行释放。
(2)malloc是分配到自由空间里面去的,使用free进行释放,一般在C中用的比较多。
(3)alloca是分配到栈空间的,由编译器对其进行管理。
分配效率不同:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持。堆是C++函数库提供的,机制比较复杂,所以栈的分配效率比堆的效率高。
总结:二者各有千秋,充分利用好堆、栈达到一个平衡就好
如果你理解了代码在内存中的存储,还会随便定义一个静态方法或是静态变量吗?以上内容都是理论,具体还要靠工程经验来说话的。