函数
函数(英文“function”)把一些经常用到的代码封装起来,这样可以减少一些冗余代码、重复的代码。一个大的程序,它是由很多很多程序块组成的,每个模块实现一个特定的功能。
函数的定义
格式
英文版
return_type function_name( parameter list ){
body of the function
return expression;
}
中文版
返回值类型 函数名(参数列表){
函数体
return 表达式 ;
}
参数列表可以是空参
- 函数定义的特性
- 返回值类型:整型、浮点型、字符类型、字符串类型、自定义类型、空类型等;
- 函数名:函数名的定义是为了调用。函数名在定义的时候,一定要明确它的用途;
- 参数列表:要传递哪些参数,格式(
表达式1
,表达式2
); - return 表达式:表达式也就是返回值;
注意:
返回值类型和返回值是配套的
如果函数的返回值类型是double,返回int变量,那么就会做强制转换,或者做隐式转换(小转大不会丢失数据,大转小会丢失数据)
函数的调用
函数是为了把常用的函数和算法、代码等进行封装,对于外部来说,这个封装的函数就是一个黑盒子,不知道里面是如何实现,可以根据函数的名,便可以知晓返回的是什么东西。
核心就是为了解决一个具体问题,并且想办法把它的效率给提升上来
代码示例
#include <iostream>
using namespace std;
int add(int a, int b) {
return a + b;
}
int max(int a, int b) {
if (a > b) {
return a;
}
return b;
}
int max1(int a, int b) {
return a > b ? a : b;
}
int sum(int n) {
//枚举算法
int ret = 0;
for (int i = 1; i <= n; ++i) {
ret += i;
}
return ret;
}
int sum1(int n) {
//公式算法
return (1 + n) * n / 2;
}
int main() {
/*1. 加法的调用和嵌套*/
int a = add(add(5, 7), 9);
int b = add(5, 7);
int c = add(b, 9);
cout << "a 的值:" << a << endl; // a 的值:21
cout << "b 的值:" << b << endl; // b 的值:12
cout << "c 的值:" << c << endl; // c 的值:21
/*2. 最大值的调用*/
int d = max(a, b);
int e = max1(a, b);
cout << "d 的值:" << d << endl; // d 的值:21
cout << "e 的值:" << e << endl; // e 的值:21
/*3. 求 1 到 n 的和*/
int n;
cin >> n; // 输入:10
//函数的调用。
int f = sum1(n);
int g = sum(n);
cout << "f 的值:" << f << endl; // f 的值:55
cout << "g 的值:" << g << endl; // g 的值:55
return 0;
}
函数值传递
-
实参与形参
- 实参: 是函数调用时传递给函数的具体值或表达式,用于初始化函数的参数列表。
- 形参:是函数定义时参数列表中声明的变量,用于接收调用函数时传入的值。
-
内存层面理解
- 实参:实参在调用函数的作用域内有自己的内存空间。
- 形参:当函数被调用时,形参在被调用函数的栈中分配新的内存空间。
-
当使用值传递时,函数的调用会为函数的每个形参拷贝一个新的副本,这些副本被初始化为对应实参的值。函数内部对形参的任何修改,都只影响这些副本,而不会影响调用函数中的实参。
注意:
函数值的传递,是申请了一部分内存出来,拷贝了一份数据运行,并不是原来的数据。
函数运行结束后,内部的局部变量就会进行销毁。
代码示例
#include <iostream>
using namespace std;
void test(int num) {
num = num + 10;
cout << "函数内部使用 num: " << num << endl; // 15
}
int main() {
int num = 5;
cout << "函数调用之前 num: " << num << endl; // 5
test(num);
cout << "函数调用之后 num: " << num << endl; // 5
return 0;
}
/*
函数调用之前 num: 5
函数内部使用 num: 15
函数调用之后 num: 5
*/
函数的声明
-
C++的函数是从上到下执行的。如果自定义的函数名在main函数下面,并且main函数中有调用这个自定义的函数名,在执行的代码过程中,就会出现报错。为了避免这个报错就需要在main函数前对调用的自定义函数进行声明。
-
函数的声明主要可能会发生在“相互调用”的场景,所以就需要进行提前声明,但是相互调用会容易造成一个死循环。所以需要对其进行条件限制。
代码示例
#include <iostream>
using namespace std;
int add(int x, int y);
void func2(int x);
void func1(int x) {
if (x <=0) {
return;
}
cout << "func1:" << x << endl; // 输出:10 8 6 4 2
func2(x - 1);
}
void func2(int x) {
if (x <= 0) {
return;
}
cout << "func2:" << x << endl; // 输出:9 7 5 3 1
func1(x - 1);
}
int main() {
int a;
int b;
cin >> a >> b; // 输入:4 5
int c = add(a, b);
cout << c << endl; // 输出:9
int d;
cin >> d; // 输入:10
func1(d);
}
int add(int x, int y) {
int z = x + y;
return z;
}
非安全函数
scanf
和 strcpy
这两个函数直接使用会出现报错(这两个是C语言的语法),报错原因:非安全函数。
解决方法1:在这两个函数后面添加一个“_s
”,变为 scanf_s
、 strcpy_s
。
解决方法2:在代码上方定义一个宏 #define _CRT_SECURE_NO_WARNINGS
。
#include <iostream>
using namespace std;
int main() {
int a;
scanf_s("%d", &a); // 5
char str[10];
strcpy_s(str, "hahaha");
printf("%d %s", a, str); // 5 hahaha
return 0;
}