C++函数参数的传递
学编程肯定会学到函数,函数里面还会设置一些参数,帮助我们解决一些繁琐的问题。参数是调用函数与被调用函数之间交换的通道,函数定义的首部的参数称为形式参数(简称形参),调用函数时使用的参数称为实际参数(简称实参)。下面是C++中函数参数的传递方式。
1、传值参数
简介:在值传递机制中,作为实参的表达式的值被复制到由对应的形参名所标识的对象中,成为形参的初值。完成参数值传递之后,函数体中的语句对形参的访问、修改都是在这个标识对象上操作的,与实参对象无关。
1)第一种格式,是在一开始就声明函数体,并赋予形参整形变量x,y,并在函数体里面对形参进行所需的运算,最后才写主函数,主函数中设置好实参a,b的值,再调用函数count将实参传回去计算。
代码如下(示例):
#include<iostream>
using namespace std;
void count(int x,int y)
{
x=x*2;
y=y*y;
cout<<"x="<<x<<'\t';
cout<<"y="<<y<<endl;
}
int main()
{
int a=3,b=4;
count(a,b);
cout<<"a="<<a<<'\t';
cout<<"y="<<b<<endl;
}
2)第二种格式,是先写主函数,再写函数体。注意:这个时候会出现报错。为什么会报错?因为主函数找不到你所调用的函数在哪里。解决办法是:在主函数之前声明该函数即可。
代码如下(示例):
#include<iostream>
using namespace std;
void count(int x,int y);//函数声明
int main()
{
int a=3,b=4;
count(a,b);
cout<<"a="<<a<<'\t';
cout<<"y="<<b<<endl;
}
void count(int x,int y)
{
x=x*2;
y=y*y;
cout<<"x="<<x<<'\t';
cout<<"y="<<y<<endl;
}
2、指针参数
简介:当函数定义中的形参被说明为指针类型时,称为指针参数。形参指针对应的实参是地址表达式。调用函数时,实参把对象的地址赋给形参名标识的指针变量,被调用的函数可以在函数体内通过形参指针来间接访问实参地址所指的对象。这种参数传递方式称为指针传递或地址调用。
1)下面的例子中,x和y分别获取了a和b的地址,然后再通过swap函数进行交换。
代码如下(示例):
#include<iostream>
using namespace std;
void swap(int *x,int *y)
{
int temp=*x;
*x=*y;
*y=temp;
}
int main()
{
int a=3,b=8;
cout<<"before swaping.....\n";
cout<<"a="<<a<<",b="<<b<<endl;
swap(&a,&b);
cout<<"after swaping.....\n";
cout<<"a="<<a<<",b="<<b<<endl;
}
2)如果我们不要指针那还会不会实现上面的交换功能呢?
代码如下(示例):
#include<iostream>
using namespace std;
void swap(int x,int y)
{
int temp;
temp=x;
x=y;
y=temp;
}
int main()
{
int a=3,b=8;
cout<<"before swaping.....\n";
cout<<"a="<<a<<",b="<<b<<endl;
swap(a,b);
cout<<"after swaping.....\n";
cout<<"a="<<a<<",b="<<b<<endl;
}
显然它没有实现,为什么?因为它的本质是按值传递的,就是x和y获得了a,b的值,但是调用函数的时候a还是原来的值,b也是原来的值。这里形参x与实参的a其实是两个不同的存储空间,所以对于形参存储单元的操作,当然不会关联实参产生变化。并且我们的swap函数返回值类型是void,即ab交换后的值并没有被传递回来,所以在main函数中,ab的值仍然没有变。
3、引用参数
简介:形参被定义为引用类型时被称为引用参数。引用参数对应的实参应该是对象名。函数被调用时,形参不需要开辟新的储存空间,形参名作为引用(别名)绑定于实参标识的对象上,执行函数体时,对形参的操作就是对实参对象的操作,直至函数执行结束,撤销引用绑定。
代码如下(示例):
#include<iostream>
using namespace std;
void swap(int &,int &);
int main()
{
int a=3,b=8;
cout<<"before swaping.....\n";
cout<<"a="<<a<<",b="<<b<<endl;
swap(a,b);
cout<<"after swaping.....\n";
cout<<"a="<<a<<",b="<<b<<endl;
}
void swap(int &x,int &y)
{
int temp=x;
x=y;
y=temp;
}
这里类似像取别名了,就是 int &x=a; int &y=b。
4、使用const引用参数
代码如下(示例):
#include<iostream>
using namespace std;
void display(const int& rk) //定义const引用参数
{
cout<<rk<<":\n"<<"dec:"<<rk<<endl<<"oct:"<<oct<<rk<<endl
<<"hex:"<<hex<<rk<<endl;
}
int main()
{
int m=2618;
display(m); //实参是变量
display(4589); //实参是常数
}
在本例main函数中第二次调用display函数时,用常数4589作为实参。C++规定,函数的const引用参数允许对应的实参为常数或者表达式。调用函数进行参数传递时将产生一个匿名对象保存实参的值。形参标识名作为这个匿名对象的引用,对匿名对象进行操作。匿名对象在被调用函数运行结束后撤销。
const引用参数的匿名对象测试
代码如下(示例):
#include<iostream>
using namespace std;
void anonym (const int &ref)
{
cout<<"The address of val is:"<<&ref<<endl;
return;
}
int main()
{
int val=10;
cout<<"The address of val is:"<<&val<<endl;
anonym(val);
anonym(val+5);
}
main函数第一次调用anonym函数时,实参是变量名。形参ref与实参val绑定。在程序输出的第1行和第2行,实参和形参的地址相同,说明引用参数与实参对象都是同一个储存单元,引用参数以别名方式在实参对象上进行操作。无论形参是否被约束,情形都一样。第2次调用anonym函数时,实参是表达式。(注意:C++为const引用建立匿名对象用于存放val+5的值。第3行输出是匿名对象的地址。只有const引用对应的实参可以是常量或表达式,非约束的引用参数对应的实参必须是对象名。 )
总结
以上就是今天要讲的内容,本文仅仅简单介绍了C++中函数参数传递的四个形式。引用参数和指针参数都不需要像传值参数那样产生实参对象数据的副本,而且引用参数不像指针参数那样通过间址访问实参对象,特别适用于大对象参数的高效操作。另外和指针参数的情形一样,为了避免被调用函数对实参对象产生不必要的修改,可以使用const限定引用。