参数的传递方式

  • 传值(by value)
  • 传址(by reference)

🐱‍🏍传递参数时发生了什么

当调用一个函数时,会在内存中建立一块特殊的区域,称为程序堆栈(program stack)**这块区域为每个函数参数提供了储存空间,也提供了函数定义的每个对象的内存空间(称这些对象为局部对象 local object)。一旦函数完成,这块内存就会被释放,或者说从程序堆栈中被pop出来
以传值的方式将对象传入函数,默认情况下其值会被复制一份,称为参数的局部性定义(local definition)即pass by value;**
若要将参数和实际对象产生关联,则可以通过传址的方式。

🦑pass by reference

  1. int ival=1024;
  2. int &rval=ival;

reference扮演着外界对象与函数内参数间的链接手柄的角色,定义一个对象是另一个对象的引用时(reference),相当于是给原来对象起了一个别名,二者指向的是同一内存地址中所存储的数值。
此外引用一旦初始化后,不能再次赋值。

  • 当以pass by reference的方式将对象作为函数的参数传入时,对象本身不会被复制——复制的是对象的地址;
  • 如果直接传入对象的地址,速度会更快,如将参数声明为reference:

    1. void display(const vector<int> &vec)
    2. {
    3. for(int ix=0;ix<vec.size();++ix)
    4. {
    5. ……
    6. }
    7. }

    引用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来清除其所占内存空间