首页 > 代码库 > C++笔记(3):函数的参数和返回值

C++笔记(3):函数的参数和返回值

刚学C++那会,做课程设计的时候总是会去网上很找别人写好的程序来参考,那时候看到函数参数列表里各种复杂的类型和奇怪的写法就头大,后来总算是慢慢搞清楚了,在此对函数各种类型的形参以及函数的返回值进行一下总结。

1.普通形参

传递普通形参也就是值传递,传递的是实际参数的一个副本,当函数被调用时,形参复制实参,也就是说此时形参和实参的值是一样的,但形参在内存中拥有自己的地址。当函数结束时形参的生命周期终止,函数内部的操作不会影响到实参的值。经典的值交换函数代码如下:

void swap1(int a, int b){  int temp;  temp = a;  a = b;  b = temp;}

当以下语句调用该函数之后,i和j的值不变,互换失败,因为在函数内p和q互换了,但并不影响i和j。

swap1(i, j);

2.指针形参

和普通形参一样,指针形参是指针实参的复制,在函数中的操作也仅限于这个副本,对指针形参本身的改变不会影响实际的指针,但可以通过指针形参修改指针所指向对象的值。依然用值交换函数为例:

void swap2(int *a, int *b){  int temp;  temp = *a;  *a = *b;  *b = temp;}

当以下语句调用该函数之后,i和j的值互换成功,因为通过指针p和q互换了它们所指地址存放的值,而i和p指向同一地址,j和q指向同一地址。

swap2(&i, &j);

3.引用形参

和所有引用一样,引用形参直接关联到所绑定到的对象,而并非是对象的副本,因此在函数中对形参的操作实际上也在对实参操作。引用形参的值交换函数如下:

void swap3(int &a, int &b){  int temp;  temp = a;  a = b;  b = temp;}

当以下语句调用该函数之后,i和j的值互换成功,因为p和q只是i和j的引用,交换p和q时实际是在交换i和j的值。

swap1(i, j);

4.const形参

const限定符的使用使得形参在函数内部只能被调用而不能被改变,由于实参仍然是一副本的形式传递,因此传递给const形参的既可以是const对象也可以是非const对象。

在编程写函数时,如果使用引用形参的唯一目的是避免复制实参,则应将形参定义为const引用。这么做可以使得调用函数更加灵活。在此举个例子,函数func( )并没有使用const形参:

int func(int &val){  return ++val;}

那么如下的调用都是错误的,因为非const引用形参只能与完全同类的非const形参对象关联,而将func的形参改为const引用就解决了这些问题。

void main( ){  const int v1 = 42;  v2 = func(v1);        //错误:v2是const的  v2 = func(0);         //错误:0不是左值  v2 = func(v1 + 2);    //错误:v1 + 2不是左值        }

5.数组形参

由于数组不能复制,因此处理数组的函数通常通过操纵指向数组中的元素的指针来处理数组,如以下三种方式:

void showArray(int*){}void showArray(int[]){}void showArray(int[10]){}

当需要严格指定数组大小时,因传递数组的引用,这时传递的不是指向数组元的指针,而是通过引用访问数组本身:

void showArray(int (&arr)[10]){}

6.函数返回值

只要不是void类型的函数都有返回值,普通类型诸如int、以及标准库类型如string作为返回值的类型就不再详细讨论了,这里说下返回的是引用的情况。

当形参是引用时,可以返回形参的引用:

const string &shorterString(const string &s1, const string &s2){    return s1,size() < s2.size() ? s1 : s2;}

此函数返回两个string类型形参中较短的那个字符串的引用。

值得注意的是,引用返回的是左值,就像下面的例子里,str所绑定的对象s本就是左值,现在不过将左值的引用返回而已,将所返回的这个引用放在等号左边,就相当于将s放在等号左边。

char &get_val(string &str, string::size_typr ix){  return str[ix];}int main(){  string s("a value");  get_val(s, 0) = ‘A‘;    //正确  return 0;}

 

最后注意一点,千万不要返回函数中局部对象的引用以及指向局部对象的指针。