第二次课程总结(9.26)
1.C++内存结构
2.动态分配空间
3.函数
C++内存结构
C++程序执行时,内存会分为五个区域:
栈(stack)
堆(heap)
静态存储区
常量存储区
代码区
栈
这个区域是有编译器现场自动申请和释放的,指针一直往往上移动,其不断向低地址扩展的,也称为向下生长,退出函数的时候就会往回退。栈用于存放函数的参数,局部变量,局部常量,函数一些寄存器的信息,函数返回的地址等信息。而栈并非无限延伸,类似于弹夹,不断放入信息但是并非无限,如果数据过大会爆栈而导致程序崩溃。
堆
编译器不会去管这个区域,可以使用new和malloc来申请内存,用delete和free去释放空间。它是程序可以使用的无序空间,其中数据都是杂乱摆放的
静态存储区
静态存储区主要来存储全局静态变量,局部静态变量,全局变量,虚函数表等。静态存储区内数据,在合适的时间创建后,程序退出时才销毁。静态存储区内数据,在合适的时间创建后,程序退出时才销毁。
常量存储区
常量存储区存储一些常量相关的东西,如全局字符串常量,常量数组,函数指针等。
代码区
代码区是存放代码的地方,这是一块只读区域。
函数
函数原型
函数原型即函数声明,用来描述函数的返回值和参数类型。当一个函数调用出现在函数定义之前,必须先对函数进行原型说明。而值得注意的是函数声明因为要确定的是参数类型和个数,所以无所谓形参实参,仅仅只需要表达类型和个数。会出现如int max(int, int);这样的形式,算是提供了微小的便利。
函数调用
C++程序由若干函数构成,各个函数的执行通过函数的调用来完成的。所定义的函数作为主调函数,而使用的函数作为被调函数,大多数情况下,主调函数和被调函数之间有数据传递关系,这种传递是依靠参数进行的,在定义函数时括号中变量名为形式参数,而调用函数函数名后为实际参数。
1传值调用
值调用是指当发生函数调用时,给形参分配内存空间,并把实参的值传递给形参。也就是说在函数定义与函数声明过程中,使得形参发生转换等一系列变化,不会影响到实参的变化。
2传地址调用
传地址调用时,实参用地址值,形参用指针变量。调用时,将实参地值赋给对应的形参指针变量,使形参指针指向实参。故在函数中可通过形参指针对实参进行间接读或写。此时则与传值调用相反,可以对主函数内容产生影响。
3引用调用
相当于在被调用函数中使用了实参的别名。于是,在被调用函数中对形参的改变,实质是对实参的直接改变。
内联函数
函数调用有一定的时间和空间开销,影响程序的执行效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数,则引入内联函数。 则在代码运行当中不是进行函数调用,而是直接引入函数体,其一般形式如下:
inline 返回值类型 函数名(<参数列表>)
{ 函数体 }
值得注意的是,一般而言内联函数结构不能过于复杂,几行即可。如果其中含有复杂的结构控制语句,如:switch和while 等,否则编译系统将该函数视为普通函数。递归函数同样不能使用内联函数。而且内联函数的定义必须出现在内联函数 的第一次被调用之前。内联函数只能 先定义后使用,不存在先声明再使用。
带缺省参数的函数
C++允许在定义函数时给其中的某个或某些形参指定缺省值,这样,当发生函数调用时,若指定实参值则用实参;如果省略了对应位置上的实参的值时,则在执行被调函数时,以该形参的缺省值进行运算。即可以在函数声明部分就给形参赋值,若实参不存在,则有声明中所赋值运算。
函数重载
函数重载是指具有相似功能的不同函数使用同一函数名,但这些同名函数的参数类型、参数个数、返回值、函数功能可以不同。编译系统将根据函数参数的类型和个数来判断使用哪一个函数。意即系统在面对多个同函数名的不同函数时,根据其声明过程中的特点来进行具体判断,在类与对象的编程中,通常会出现多个函数为表意思而使用同一个函数名的现象。这种支持表现了C++语言对多态性的支持,也是优化了程序员的工作流程。