美文网首页
C++入门学习之函数

C++入门学习之函数

作者: 随波逐流007 | 来源:发表于2016-11-09 11:40 被阅读15次

1.函数重载

在使用函数之前,我们应该声明它。函数的声明被称为函数的原型,表示函数的调用约定,包括调用参数的个数和类型,返回值,以及由谁去堆栈等等….

关于函数,我们首先介绍一下函数重载。函数重载时C++引入的一个新的特性。多个函数具有相同的函数名,这些函数中只是参数个数和类型不同,它们就构成了重载。

我们来定义一个函数,返回两个数之间的最大值。

int max(int a, int b);

double max(double a, double b);

如果我们通过max(20,40);来调用的话,它会根据参数的个数和类型来调用第一个函数。我们也可以看通过max(20.1,40.0);来调用第二个函数。

2.内联函数

函数调用,尤其是频繁的函数调用是有一定代价的,因为它伴随着参数的传递,代码的入栈,堆栈平衡等等….为了避免这种代价,我们可以将函数声明为内联函数。在声明为内联函数之后,编译器会将调用内联函数的地方展开,将内联函数的代码嵌入到调用内联函数的地方。

内联函数的使用方法,在函数声明的前面加上inline。如:

inline void func(){

int i=0; i++;

}

如果我们在下面这样调用它:

func();

编译器就会将代码嵌入到这个地方,成了这样的形式,这样就没有了函数的调用。

int i=0; i++;

注意:使用内联函数可以节省运行时间,但是它有一个缺点,它会使你的应用程序体积增大。一般只是将代码段比较短(三到五行),调用比较频繁的函数声明为内联函数。即使你将一些复杂的函数声明为内联函数,具体是否嵌入代码这个是由编译器来决定的。编译器会根据一定的办法来判断它。

3.函数调用

C++的内存分为两部分,堆和栈。关于局部变量,函数参数的都是从栈中分配的。栈的特性是先入后出。大家学习过C,对函数的调用原理也比较清楚,函数的调用是通过栈来实现的。

下面我们来回顾一下栈:

比如a调用了B函数,首先a会讲B函数需要的参数入栈,接着会压入A中的返回地址,然后在栈中分配局部变量给函数使用。在函数执行完毕之后,在栈中会弹出函数返回地址到a中,此时分配给B函数的栈空间被回收。局部变量,函数参数占用的栈空间被释放。

下面我们来回顾一下堆:

内存是有操作系统管理的,应用程序可以向操作系统申请。但是应用程序向操作系统申请的代价是很大的,需要考虑到多线程的一些东西。这个时候就引入了堆。我们可以把堆比喻成向操作系统批发内存的零售商,它一次性从操作系统批发了一大片的内存,然后零售给我们的应用程序使用。因为没有多次从操作系统申请,所以操作代价比较小。堆一般随着应用程序的启动而分配,随着应用程序的退出而销毁。所以堆在整个运行期间都是可以使用的。

在C中,我们通过malloc来分配空间,用free来释放空间。

下面来举一个例子。

int *p=(int *)malloc(sizeof(int)*100); //申请一片可以存储一百个int变量的值的内存

if(!p){ //判断空间分配是否成功,分配失败就退出

return 0;

}

free (p); //释放内存

p=NULL; //当释放完这一片内存之后,p就已经不应该再指向这一片内存了。

为了防止误用,我们就把p指向NULL。如果不指向NULL,p就被称为野指针,野指针会导致一些问题。

在C++中,我们使用new来分配空间,用delete来释放空间。

int *p=new int[100]; //new会自动计算需要的长度,分配一连片的内存

if(!p){ //判断空间分配是否成功,分配失败就退出

return 0;

}

delete []p; //上面是数组的分配空间,所以释放的时候需要在变量名前加[]

p=NULL;

如果只是普通的变量申请和释放,只需要如此:

int *p=new int;

delete p; //不需要[],对应的申请内存的方式一定要匹配。

注意:使用new申请的内存在必须使用delete才可以释放,而释放的形式也必须匹配。

原文链接:http://www.maiziedu.com/wiki/cplus/start/

相关文章

网友评论

      本文标题:C++入门学习之函数

      本文链接:https://www.haomeiwen.com/subject/tygzuttx.html