参数传递

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

非引用形参

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

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); //ok

int 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值