C++(四)函数、变量

一、函数

函数(function),翻译过来就是功能的意思。也就是说一个函数肯定会实现或者完成某个功能。函数名命名时最好起一个能表达该函数功能的名字。

  1. 每个程序都必须至少有一个函数,C++程序主入口函数 main(只能写成这样)。
  2. 随着程序的功能越来越复杂,那么就不可能把所有的代码都写到main函数中,这时候就可以按照功能来写一个一个的函数了,之后调用。
  3. 如果程序的功能很多,比如在公司的项目中,由多个人来共同完成一个项目,那么就可以把这个项目拆分开,每个人负责几个功能函数,写好了之后再组合到一块,方便协同开发。
函数的声明与定义

①、函数的声明?
函数的声明就是告诉系统,或者告诉编译器,某个函数的基本信息,包括:函数名、有几个参数,每个参数的类型,函数的返回值类型等等。目的就是为了让编译器知道函数的信息,好让编译通过。

例如:
int add(int x, int y); //注意结尾的分号

②、函数的定义/实现?
函数的定义就是函数真正的实现,也就是函数实现的真正代码。
例如:
int add(int x, int y) // int x, int y 是形式参数,简称形参,因为函数调用之前他们并没有申请任何内存;
{
return x + y; //x,y实际运算得值,就是实参
}

形参大家可以理解为是一个模具,你给我传什么我就用什么。实参可以理解为往模具里面添加的真实物料;

函数的几种调用方式

①、普通语句调用:
②、表达式调用:
③、函数参数调用:
④、嵌套调用:
函数的嵌套调用意思就是:函数a调用了函数b,函数b又调用了函数c…就这样一层一层的调用下去!
注意:C++ 中函数可以嵌套调用,不允许函数的嵌套定义!

⑤、递归调用:
在调用一个函数的过程中又出现或者有需要直接或间接的调用该函数本身,即自己调用自己,这样的情况称作函数的递归调用,在C/C++语言中是允许的。但要注意不能无限递归,那样的话就类似死循环了,应该竭力避免,必须要有最终能跳出递归的条件。

举个例子:
教室里一排共计10个人,问第10个人几岁了,他说我比第9个人大两岁,问第9个人几岁了,他说我比第8个人大两岁,问第8个人几岁了…,问第2个人几岁了,他说我比第1个人大两岁,问第1个人几岁了,他说我今年10岁了(这个就是最终跳出递归的条件)。问题是:问第10个人几岁了?

小案例:求数得阶乘

#include <iostream>
using namespace std;

double factorial(unsigned int i)
{
   if(i <= 1)
   {
      return 1;
   }
   return i * factorial(i - 1);
}

int  main()
{
    int i = 15;
    cout << i << "的阶乘为: " << factorial(i) << endl;
    return 0;
}
函数的返回值

一般情况下,通过函数的调用,使调用函数可以获得被调用函数的函数值,这个值就叫做返回值。
注意事项:
①、有的函数有返回值,有的函数没有返回值,具体看函数的声明类型,如果返回值类型为 void 则为无返回值类型;
②、函数的返回值是通过函数中的 return 语句获得的。一个函数中可以有一个以上的return语句,执行到哪个return就从哪个return返回了,return语句执行完之后,他之后的代码不会被执行;
③、函数内部的return返回值类型要与函数本身定义时候的返回值类型一致,即使不一致也是可以相互转化的,最终以函数定义时候的返回值类型为主进行转化,若转化不了则编译期间就报错了;
④、原则上一个函数只能有一个返回值,若要返回多个值则可以通过参数返回或者返回结构类型等等,比如:指针等等。

二、内联函数

内联函数由来:

  1. 平常中,使用函数能够避免将相同代码重写多次的麻烦,还能减少可执行程序的体积,但也会带来程序运行时间上的开销。
  2. 函数调用在执行时,首先要在栈中为形参和局部变量分配存储空间,然后还要将实参的值复制给形参,接下来还要将函数的返回地址(该地址指明了函数执行结束后,程序应该回到哪里继续执行)放入栈中,最后才跳转到函数内部执行。这个过程是要耗费时间的。
  3. 函数执行 return 语句返回时,需要从栈中回收形参和局部变量占用的存储空间,然后从栈中取出返回地址,再跳转到该地址继续执行,这个过程也要耗费时间。
  4. 使用函数调用语句和直接把函数中的代码重新抄写一遍相比,节省了人力,但是带来了程序运行时间上的额外开销。一般情况下,这个开销可以忽略不计。但是,如果一个函数内部没有几条语句,执行时间本来就非常短,那么这个函数调用产生的额外开销和函数本身执行的时间相比,就显得不能忽略了。假如这样的函数在一个循环中被上千万次地执行,函数调用导致的时间开销可能就会使得程序运行明显变慢。

作为特别注重程序执行效率,适合编写底层系统软件的高级程序设计语言,C++ 用 inline 关键字较好地解决了函数调用开销的问题。 所以:把执行体很小,而且会被频繁的调用的函数 作为 inline 内联函数才合适

内联函数优点:
① 阅读和理解函数 max 的调用,要比读一条等价的条件表达式并解释它的含义要容易得多
② 如果需要做任何修改,修改函数要比找出并修改每一处等价表达式容易得多
③ 使用函数可以确保统一的行为,每个测试都保证以相同的方式实现
④ 函数可以重用,不必为其他应用程序重写代码

内联函数的定义与使用,在返回值类型前面加上 inline 关键字

#include<iostream>
using namespace std;

inline double square(double x)
{
    return x*x;
}


int main()
{
   double a;
   a = square(5.0);
   cout << "a= " << a << endl;
   return 0;
}

内联函数是C++特性,C语言使用#define来提供宏,这是内联函数的原始实现。
C语言中可以用宏来实现一些相对简单的函数,

例如:
#define MAX_NUM(x, y) (x > y ? x : y)  //定义宏
int ret = MAX_NUM(3, 6);       //调用

调用的时候感觉 MAX_NUM 像个函数,但是他是个宏,宏跟函数的区别是,在编译阶段就将宏的代码展开直接替换调用宏的地方。所以省去了函数调用的压栈、出栈等开销。所以执行效率方面要比函数高。

三、变量

一般的变量定义:
type variable_name = value;

举例:

// 变量声明
extern int a, b;
extern int c;
extern float f;

// 变量声明与初始化
int i = 0;
char ch='w';
float  f = 10.0, salary = 30.0;
double d = 20.0;
3.1 局部变量与全局变量

举个例子:张三是101班的的班主任(局部变量),李四是102班的班主任(局部变量),那么张三班的同学有什么事儿都可以去找张三,张三也对该班存有管辖权。李四班的同学有什么事儿都找到李四这个班长了。张三班的同学有什么事儿不能李四,找李四,李四也不认识。那么这时候呢如果出来个王五校长,那么就方便多了。张三班和李四班的同学都可以直接找王五校长(全局变量)解决问题。

#include <iostream>
using namespace std;

int sum = 0;            //全局变量:sum 
int add(int a, int b)
{
	int ret = a+b;      //局部变量:a,b,ret 这三个add函数可以访问
	return ret;
}

int main()
{
	int x = 2, y = 5;   //局部变量:x,y 这两个main函数可以访问
	sum = add(x, y);
	cout << "sum = " << sum << endl;
	return 0;
}

注意点:
①、函数内部定义的局部变量也只能在该函数中使用,其他的函数无法调用,例如:main 函数中的 x 和 y 在 add 函数是无法访问的。add函数中的 ret 在 main 函数中也是无法访问的;
②、不同函数或者作用域内可以定义相同名字的局部变量名字,虽然名字相同,但都是不同的个体,互不影响,彼此独立;
③、一般局部变量的作用域就在他所在的一对花括号内,函数的形参作用域也在其函数的整个作用域内,也是局部变量;
④、全局变量的定义要尽量靠上,不然在他上面的函数使用不了,因为本身编译器编译代码的顺序就是自上向下。

多文件共同访问一个全局变量:
①、在其中一个C/Cpp文件中定义并初始化全局变量,例如:
int sum = 0;
②、在C/Cpp文件都能访问到的一个h头文件中声明该全局变量为支持多文件访问的:
extern int sum; //此时只是声明,所以不需要初始化。
③、在其他C/Cpp文件中 #include 这个头文件之后,就可以直接使用这个全局变量 sum 了。

备注:在 h 头文件中声明全局变量,且有多个C/Cpp文件 include 包含这个头文件的时候,只能写成 extern type var_name(例如:extern int sum)。不能初始化,否则就会提示 sum 重复定义了。

3.2 static 静态类型变量

static 静态类型局部变量只初始化一次,之后的调用都不进行初始化!

#include <iostream>
using namespace std;

int sum = 0;
int add(int a, int b)
{
	static int num = 1;
	int ab = a+b;
	ab += num;
	++num;
	return ab;
}

int main()
{
	int x = 2, y = 5;
	sum = add(x, y);
	cout << "sum = " << sum << endl;

	sum = add(x, y);
	cout << "sum = " << sum << endl;

	sum = add(x, y);
	cout << "sum = " << sum << endl;
	return 0;
}

=============
输出如下:
sum = 6
sum = 7
sum = 8
=============
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页