参数传递

来源:互联网 发布:汕头美工助理招聘信息 编辑:程序博客网 时间:2024/06/03 18:32

形参的初始化与变量的初始化一样:如果形参具有非引用类型,则复制实参的值,如果形参为引用类型,则它只是实参的别名.

非引用形参

普通的非引用类型的参数通过复制对应的实参实现初始化,不会改变实参本身的值.对这类形参的值得修改仅仅改变局部副本的值,当被调用函数执行完时,这些局部副本的值也将不存在.

1. const 形参

在调用函数时,如果该函数使用非引用的非const形参,则①既可以给该函数传递const实参,②也可以传递非const的实参。比如函数

int gcd(int v1,int v2){    while(v2)    {        int temp=v2;        v2=v1%v2;        v1=temp;    }    return v1;}const int i=3,j=6;int k=gcd(3,6); //okint i=3,j=6;int k=gcd(3,6); //ok

2. 形参为非引用的const类型

void fcn(const int i)  /*fcn can read but not write to i*/

则不可以改变实参的局部副本,由于实参仍然是以副本的形式传递,因此传递给fcn的既可以是const对象,也可以是非const对象。

3. 复制实参的局限性

不适宜复制实参的情况包括:

  • 当需要在函数中修改实参的值
  • 当需要以大型对象作为实参传递时
  • 没有办法实现对象的复制时

引用形参

函数swap要求交换两个实参的值,这时不适宜复制实参的值,所以这时用引用形参更方便。

void swap(int &v1, int &v2){    int temp=v2;    v2=v1;    v1=temp;}

引用形参直接关联到其绑定的对象,而非这些对象的副本,当调用swap()时,

swap(i, j);

形参v1只是对象i的另一个名字,对v1的任何修改实际上都是对i的修改。

利用引用形参的另一个好处是可以返回额外的信息,比如遍历vector中某个特定的元素,如果找到满座条件的元素,则返回指向该元素的迭代器,否则返回一个指向end的迭代器;此外,还希望返回该值出现的次数。

vector<int>::const_iterator find_val(vector<int>::const_iterator beg,vector<int>::const_iterator end,int val,vector<int>::size_type &occurs){    vector<int>::const_iterator res_iter=end;    occurs=0;    for(;beg!=end;++beg)    {        if(*beg==val)        {            if(res_iter==end)            {                res_iter=beg;            }         ++occurs;        }    }    return res_iter;}

当对象较大时,利用const引用避免复制。比如比较两个string对象的长度:

bool isShorter(const string &s1, const string &s2){    return s1.size()<s2.size();}

每个形参都是const string 类型的引用,因为形参是引用,所以不复制形参,又因为形参是const引用,所以isShorter函数不能使用该引用来修改实参。

注意:如果使用引用形参的唯一目的是避免复制实参,则应将形参定义为const引用。


形参为指针的引用

两个指针的交换:

void ptrswap(int *&v1, int *&v2){    int *temp=v2;    v2=v1;    v1=temp;}

形参 int *&v1, 的定义应从右至左理解:v1是一个引用,与指向int型对象的指针相关联。


数组形参

作用在函数上的数组的两个特性:一是不能复制数组,二是使用数组名字时,数组名会自动转化为指向其第一个元素的指针。所以通常通过操纵指向数组中的元素的指针来处理数组。

  • 数组参数的定义:
void printValues(int *)void printValues(int [])void printValues(int [10]) //最好别这样写,形参的长度容易引起误解

函数形参可以写成数组的形式。上面三种定义等价,形参类型都是int *。

  • 通过引用传递数组。
    如果形参是数组的引用,编译器不会将数组传化为指针,二是传递数组的引用本身,这种情况下,数组的大小成为形参和实参类型的一部分。编译器检查数组实参的大小与形参的大小是否匹配。
void printValues(int (&arr)[10])int main(){    int i=0,j[2]={0,1};    int k[10]={1,2,3,4,5,6,7,8,9,0};    printValues(&i);  //error    printValues(j);   //error    printValues(k);   //ok}
0 0
原创粉丝点击