C++的那些事:函数全解析

来源:本站
导读:目前正在解读《C++的那些事:函数全解析》的相关信息,《C++的那些事:函数全解析》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《C++的那些事:函数全解析》的详细说明。
简介:函数全解析

一、函数的结构

image

函数在C++中可能出现在三种地方,一是函数的定义,它包括了如上图的结构;二是函数的声明,它与函数的定义相比,没有了函数体部分;三则是函数的调用。当然,不同的函数定义可以还会稍有不同,比如类的成员函数、内联函数等。这里我们主要讨论函数的调用时需要注意的一些问题。

二、参数传递

我们将函数定义或声明里的参数叫形参,而在调用函数时传入的参数叫实参。那么根据形参类型的不同,有几下形式的参数传递。

1,非引用形参

1)普通的内置类型

普通非引用类型的参数通过复制对应的实参实现形参的初始化。当用实参的副本初始化形参时,函数并没有访问调用所传递的实参的本身,因此函数不可能改实参的值。比如下面的交换两个数的程序:

复制代码

void swap(int v1, int v2)

{

int temp = v1;

v2 = v1;

v1 = temp;

}

swap(a, b);// 调用swap

复制代码

上面程序中,实参为a与b,但是在调用时,v1与v2接受的是a与b的副本,所以实际上a与b的值没有变化。

2)指针形参

函数的形参可以是指针,此时将复制实参指针,其实这类跟1)原理类似,函数内并无法改变实参的指针值。只是函数可以通过复制到的地址改变实参指针所指向的值。

复制代码

void swap(int* v1, int* v2)

{

int temp = *v2;

*v2 = *v1;

*v1 = temp;

}

int main()

{

int a = 10,b = 20;

int *p1 = &a,*p2 = &b;

swap(p1,p2);

return 0;

}

复制代码

上面程序中定义的swap的形参为指针类型,main中调用swap,实际上swap并不能改变p1与p2的值,只是改变了它们所指向的值。

3)const 形参

对于普通的非引用类型用const修饰实际上是没有意义的,因为本来函数就不会改变实参的值。像下面的定义,实际中编译器会忽略const的定义,而将其视为int型。

void fcn(const int i);

2,引用形参

1)在上面的程序中我们看到,如果想交换两个变量的值,通过调用普通的非引用类型形参的函数,并不能实现。用它们的指针可以,同时我们也可以用引用。

复制代码

void swap(int& v1, int& v2)

{

int temp = v2;

v2 = v1;

v1 = temp;

}

int main()

{

int a = 10,b = 20;

swap(a,b);

return 0;

}

复制代码

在实际调用swap时,v1与v2实际相当于a与b的另一个名字。

2)在有的时候我们需要向函数传递大型对象,需要使用引用形参,如果直接使用复制实参的形式可以,但是它的效率太低了,甚至有些对象是无法复制的。但是使用引用形参时,我们不希望函数改变了实参传入的值,我们就可以使用const来限定形参。下面程序用来判断哪个字符串更长,明显我们不希望函数会改变字符串的内容,我们就可以用const引用型的形参。

bool isLonger(const string &s1, const string &s2)

{

return s1.size() > s2.size();

}

所以,如果使用引用形参的惟一的目的是避免复制实参时,则应将形参定义为const引用。

3)在使用引用形参函数时,有两点值得注意:

不要用const限定的实参或字面值来调用非const引用形参函数。因为这样函数内,可以改变实参的值,这不合法。

非const引用形参只能与完全同类型的非const对象关联。

4)传递指向指针的引用

如下有下面的程序:

复制代码

void swap(int* &v1, int* &v2)

{

int* temp = v2;

v2 = v1;

v1 = temp;

}

int main()

{

int a = 10,b = 20;

int* p1 = &a, *p2 = &b;

swap(p1,p2);

return 0;

}

复制代码

上面的程序依然不能改变a与b的值,但是它改变了p1与p2的值,现在p1指向了b,而p2指向了a.

3,其他类型的形参

1)vector和其他类型的形参:一般在这种类型作为形参时,为了避免复制应该考虑形参声明为引用类型。C++程序员倾向于传递容器中需要处理的元素的迭代器来传递容器。

2)数组形参:由于数组不能复制,所以不能直接编写数组类型的形参函数,一般通过传递指向数组的元素的指针来处理数组。值得注意的是在通过引用传递数组时,在调用函数时形参与实参的类型要匹配。

复制代码

void printValues(int (&ar)[10]);

int main()

{

int i = 0, j[2] = { 0, 1 };

int k[10] = {0,1,2,3,4,5,6,7,8,9};

printValues(i); //error int不能初始化 int(&)[10]

printValues(j); //error int[2] 不能初始化 int(&)[10]

printValues(k); // ok

return 0;

}

复制代码

二、函数的返回值

1)没有返回值

很多函数并没有返回值,尤其是现在C++风格,习惯于把需要的结果作为引用形参。这类型函数一般没有return语句,有时候有return是使函数中途中断执行。

2)返回非引用类型

这种情况在函数调用处,程序会用一个临时变量复制函数的返回值。

3)返回引用

当函数返回引用类型时,并没有复制返回值。相反,返回的是对象本身。

在返回引用这种情况下,注意不要返回局部变量的引用,因为局部变量在函数体内定义,当函数执行完后就销毁了,所谓的引用也就没有意义了。同理,不要返回指向局部变量的指针。

三、重载函数

出现在相同作用域中的两个函数,如果具有相同的名字而形参不同,则称为重载函数。

1)注意区分函数重载与重复声明

有些看起来不同的形参,本质是相同的。下面代码中的都是重复声明的例子

复制代码

typedef double newDouble;

int func(double i);

int func(newDouble i); // 没有新类型

int func1(int, int = 1); //只是提供默认参数

int func1(int ,int);

int func2(int);

int func2(const int); //对于普通非引用形参用cosnt修饰是没有意义的

提醒:《C++的那些事:函数全解析》最后刷新时间 2024-03-14 01:04:52,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《C++的那些事:函数全解析》该内容的真实性请自行鉴别。