参数的传递方式
- 传值(by value)
- 传址(by reference)
🐱🏍传递参数时发生了什么
当调用一个函数时,会在内存中建立一块特殊的区域,称为程序堆栈(program stack)**,这块区域为每个函数参数提供了储存空间,也提供了函数定义的每个对象的内存空间(称这些对象为局部对象 local object)。一旦函数完成,这块内存就会被释放,或者说从程序堆栈中被pop出来。
以传值的方式将对象传入函数,默认情况下其值会被复制一份,称为参数的局部性定义(local definition)即pass by value;**
若要将参数和实际对象产生关联,则可以通过传址的方式。
🦑pass by reference
int ival=1024;
int &rval=ival;
reference扮演着外界对象与函数内参数间的链接手柄的角色,定义一个对象是另一个对象的引用时(reference),相当于是给原来对象起了一个别名,二者指向的是同一内存地址中所存储的数值。
此外引用一旦初始化后,不能再次赋值。
- 当以pass by reference的方式将对象作为函数的参数传入时,对象本身不会被复制——复制的是对象的地址;
如果直接传入对象的地址,速度会更快,如将参数声明为reference:
void display(const vector<int> &vec)
{
for(int ix=0;ix<vec.size();++ix)
{
……
}
}
引用vs指针
不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能再次被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
作用域及范围
函数内定义的对象,只存在于函数的执行期间;
一些名词解释:
- 为对象分配的内存,其存活时间称为储存期(storage duration)或范围(extent)
- 对象再程序内存活的区域称为该对象的scope(作用域)
- 如果某个对象仅具有local scope(局部作用域),其名字再local scope之外便是不可见的
- 对象如果再函数外声明,就具有file scope(全局作用域)从其声明点到文件末尾都是可见的;
- 内置类型的对象,若定义为file scope,必定被初始化为0,若定义为local scope,那么除非给出初值,否则不会被初始化。
动态内存管理
局部变量和全局变量是由系统自动管理,而第三种形式的变量被称为dynamic extent(动态范围)其内存由程序的空闲空间(free store)分配而来,有时也称作堆内存(heap memory)。这种内存由程序员自行管理,通过new表达式来分配,释放通过delete表达式完成。
new表达式: new Type:
如 int *p; p=new int;
如因为某种原因程序员在new后未使用 delete;
那么内存就不会被释放,即发生了内存泄漏 memory leak
小结
- 函数参数调用有两种方式:传值和传址(引用 or 指针)
- 引用需要在定义时初始化,且不可再次定义
- 使用new方式定义变量时,需要delete来清除其所占内存空间