- 栈
现在计算机都直接在代码底层支持栈的结构,这体现在,底层有专门的寄存器指向栈所在的地址(SS,堆栈段寄存器,存放堆栈段地址);有专门的机器指令完成这种入栈出栈的操作(push,pop)。
这种机制效率较高,但支持的数据类型较少,一般是整数,浮点,指针等系统直接支持的数据类型,并不支持其他的数据结构(自定义栈)。因为这种特点,栈在程序中的使用特别频繁,对于子程序的调用,就是直接利用栈完成的,机器的call指令中隐含了把返回地址入栈,而子程序的ret指令则是从堆栈中弹出返回地址并跳转的操作。 堆
堆是由函数库提供的而不是系统支持,基本malloc/calloc/realloc/free函数维护了一套内部的堆结构(在C++中则增加了new/delete维护)。
内存区介绍
内存主要分为五个区域:
(1) 栈(stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。
(2) 堆(Heap):这部分是由new申请的内存,由delete或者delete[]负责释放。
(3) 自由存储区(Free Storage):由程序中的malloc、calloc、realloc分配,free释放,如果未释放将造成内存泄漏,程序结束时由OS回收。
(4) 全局区/静态区(Global Static Area):全局变量和静态变量存放区,程序编译好之后,在程序初始化的时候,全局变量和静态变量会被初始化赋值,没有区分初始化变量和未初始化变量,需要表明一点,全局静态变量和局部静态变量都是存储在同一个静态区,只是作用域不同。
(5) 常量存储区:比较特殊的区域,专门用来存储一些不可修改的常量(一般是指const变量,也有一些常量字符串)。
指针和引用的异同
1. 指针
指针传递参数实质上是值传递,它所传递的是一个地址值。值传递的过程中,被调函数的形式参数作为被调用函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行的,不会影响主调函数的实际参数的变量的值。
2. 引用
在引用传递中,被调函数的形式参数虽然也是作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数传入的实参的地址(int &a的形式),被调函数对形参的任何操作都是间接寻址,即通过栈中的地址直接访问主调函数中实参的地址,所以在被调函数中修改形参时会对主调函数的实参有影响。
指针和引用的相同点
都要地址的概念,指针指向一块内存,他的内容就是所指内存的地址,而引用则是那块内存的别名。
指针和引用的不同点
(1)指针是一个实体,而引用只是一个别名。
(2)引用只能在定义时被初始化一次,之后不可变;指针可变。引用 “从一而终”,指针 “见异思迁”。
(3)引用没有const,指针有const,const的指针不可变;(存在const int &a,表示引用的值不可变)。
(4)引用不能为空,指针可以为空。
(5)“sizeof 引用” 得到的是引用对象的大小,“sizeof 指针”得到的只是指针本身的大小。
(6)指针和引用的自增++意义不一样。
(7)引用是类型安全的,而指针不是(引用比指针多了类型检查)。
性能上的区别
在传大型对象的时候,传引用比传指针好,引用不会拷贝副本,而指针会。