您的位置:首页 > 编程语言 > C语言/C++

C++Primer:函数(参数传递-非引用形参)

2016-06-03 15:55 375 查看

1.参数传递

每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会初始化对应的形参。
形参的初始化与变量的初始化一样;如果形参具有非引用类型,则复制实参的值,如果形参为引用类型,则他只是实参的别名。

2.非引用形参

普通的非引用类型的参数通过复制对应的实参实现初始化。当用实参副本初始化形参时,函数并没有访问调用所传递的实参本身,因此不会修改实参的值
非引用形参表示对应实参的局部副本。对这类形参的修改仅仅改变了局部副本的值。一旦函数执行结束,这些局部变量的值也就没有了。

2.1 指针形参

函数的形参可以是指针,此时将复制实参指针。与其他非引用类型的形参一样,该类形参的任何改变也仅作用于局部副本。如果函数将新指针赋给形参,主调函数使用的实参指针的值没有改变。
事实上,被复制的指针只影响对指针的赋值。如果函数形参是非const类型的指针,则函数可通过指针实现赋值,修改指针所指向对象的值。
<span style="font-size:18px;">#include <iostream>
using std::cout;
using std::endl;
void Reset(int* ip);

int main()
{
int i = 100;
int* p = &i;
cout<<"Befor"<< *p<<endl;
Reset(p);
cout<<"After"<<*p<<endl;
return 0;
}
void Reset( int* ip)
{
*ip = 0;
ip = 0;
}</span>
上述程序运行结果为 100,0;
解释:调用reset后,实参依然保持原来的值(指的是指针的名字,而非指针指向的内容),但是它所指向的对象的值将变为零。
如果保护指针指向的值,则形参需定义为指向const对象的指针
#include <iostream>
using std::cout;
using std::endl;
void Reset(const int* ip);

int main()
{
int i = 100;
int* p = &i;
cout<<"Befor"<< *p<<endl;
Reset(p);
cout<<"After"<<*p<<endl;
return 0;
}
void Reset(<strong><span style="color:#3333ff;">const</span></strong> int* ip)
{
<span style="color:#ff6666;"><strong>*ip = 0;</strong></span> //error:不能给指向const int类型的指针赋值
ip = 0;
}
指针形参是指向const类型还是非const类型,将影响函数调用所使用的实参。我们既可以用int*也可以用const int*类型的实参调用Reset()函数;但仅能将int*类型的实参传递给Reset函数。这个差别来源于指针的初始化规则:
可以将指向const对象的指针初始化为指向非const对象
<p><span style="font-family: Arial, Helvetica, sans-serif;">i = 100;</span></p>const int* cip = &i; //OK:This is Right
但不可以让指向非const 对象的指针指向const对象;
const int i = 100;
int* ip = &i; //error C2440: “初始化”: 无法从“const int *”转换为“int *”

2.2 const形参

在调用函数时,如果该函数使用非引用的非const形参,则既可以给该函数传递const实参,也可以传递非const
的实参。例如:
int gcd(int v1, int v2) // 求最大公约数
{
while(v2)
{
int temp = v2;
v2 = v1 % v2;
v1 = temp;
}
return v1;
}

int main()
{
const int i = 3, j = 6;
int k = gcd(3,6); //OK,k initialized to 3
}

这种行为源于const对象的标准初始化规则。因为初始化复制了初始化式的值,所以可用const对象初始化非const对象,反之亦然。
如果将形参定义为非引用的const类型:
void fcn(const int i) { /* fcn can read but <strong><span style="color:#ff0000;">not write to i</span></strong> */ }

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


3. 复制实参的局限性

复制实参并不是在所有的情况下都合适,不适宜复制实参的情况包括:
1.当需要在函数中修改实参的值时;
2.当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出的时间和存储空间代价往往过大;
3.没有办法实现对象的复制时。
对于上述几种情况,有效的解决办法是将形参定义为引用或指针类型
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: