简介
当我们调用一个函数时,第一件事就是创建形参的那两个变量,并将这两个变量初始化为调用函数时传递的实参值。
当我们使用普通的形参(非引用类形参)时,实参对形参的初始化就是直接执行复制操作,将实参的值复制给形参。在本节和后面讨论引用类型(7.2.2节)的形参时会讨论到这个问题,就是直接执行复制有时候会效率很低——(7.1节)
每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会初始化对应的形参。
- 当用实参副本初始化形参时,函数并没有访问调用所传递的实参本身,因此不会修改实参的值。
非引用形参表示对应实参的局部副本,对这类形参的修改仅仅改变了局部副本的值,一旦函数执行结束,这些局部变量的值也就没有了。
函数的形参可以是指针,此时将复制实参指针,与其他非引用类型的形参一样,该类形参的任何改变也仅作用与局部副本,如果函数将新指针赋给形参,主调函数使用的实参指针的值没有改变;
复制实参并不是在所有的情况下都适合,不适宜复制实参的情况如下,在如下的情况中,有效的解决办法是将形参定义为引用或指针类型:
当需要在函数中修改实参的值时;
当需要以大型对象作为实参传递时,对实际应用而言,复制对象所付出的时间和存储空间代价往往过大;
当没有办法实现对象的复制时。
important
=========================================================================================================
一、非引用形参
1、非引用形参
每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会初始化对应的形参。
当用实参副本初始化形参时,函数并没有访问调用所传递的实参本身,因此不会修改实参的值。
非引用形参表示对应实参的局部副本,对这类形参的修改仅仅改变了局部副本的值,一旦函数执行结束,这些局部变量的值也就没有了。
事实上被复制的指针只影响对指针的赋值,如果函数形参是非const类型的指针,则函数可以通过指针实现赋值,修改指针所指对象的值。
如果需要保护指针所指向的值,则形参需定义为指向const对象的指针( const int * p)
int gcd(int v1,int v2){
while(v2){
int temp=v2;
v2=v1%v2;
v1=temp;
}
return v1;
}
//while 循环虽然修改了v1和v2的值,但这些变化仅限于局部参数,而对调用gcd 函数使用的实参没有任何影响。
2、指针形参
函数的形参可以是指针,此时将复制实参指针,与其他非引用类型的形参一样,该类形参的任何改变也仅作用与局部副本,如果函数将新指针赋给形参,主调函数使用的实参指针的值没有改变;
指针形参是指向const 类型还是非const类型,将影响函数调用所使用的实参。
事实上被复制的指针只影响对指针的赋值,如果函数形参是非const类型的指针,则函数可以通过指针实现赋值,修改指针所指对象的值。
如果需要保护指针所指向的值,则形参需定义为指向const对象的指针( const int * p)
void reset(int * p){
*ip=0;//修改ip指针所指对象的值
ip=0;//仅仅修改ip 局部副本的值
}
//调用reset后,实参依然保持原来的值,但它所指对象的值将变成0
int i=42;
int *p=&i;
cout<<"*i:"<<*p<<endl;//输出42
reset(p);//修改指针所指对象的值
cout<<"i:"<<*p<<endl;//输出 0
//将指针定义为指向const对象的指针,保护指针所指的对象
void use_ptr(const int *p)
{}
//指向const对象的指针可以用const和非const对象进行赋值,但是不能通过指针对其所指对象的值进行修改。
//
看《 C++primer 4.2 指针和const限定符(3)》
3、const 形参
如果在函数使用非引用的非const形参,则既可以给该函数传递const实参,也可以传递非const的实参。(就像你可以给一个非const对象赋值一个const或非const的值);
如果形参定义为非引用类的const类型,则在函数中,不能改变实参的局部副本,但是可以通过const和非const给形参赋值。(可以给一个const对象赋值一个const或非const的值)
const int i=3,j=6;
int k=gcd(3,6);//实参是const非引用的,形参不是const非引用的
void fcn(const int i);//形参定义为const类型,实参可以是
4、复制实参的局限性
复制实参并不是在所有的情况下都适合,不适宜复制实参的情况如下,在如下的情况中,有效的解决办法是将形参定义为引用或指针类型:
当需要在函数中修改实参的值时;
当需要以大型对象作为实参传递时,对实际应用而言,复制对象所付出的时间和存储空间代价往往过大;
当没有办法实现对象的复制时。