自创武功

    有些少侠一定要问了之前我们所学的怎么都是使用C/C++标准库的函数呢?我们可不可以自己自创一些函数(武功)呢?

    那么带着疑问我们来学习一下怎么自创函数(武功)。

    

为什么要使用函数

1)“避免重复制造轮子”,提高开发效率
2)便于维护

    

函数的定义

    函数的设计方法:
        1)先确定函数的功能
        2)确定函数的参数,是否需要参数,参数的个数,参数的类型
        3)确定函数的返回值,是否需要返回值,返回值的类型
        4)确定函数名,函数名, 一定要顾名思义.
        5)函数名的命名方法, 和变量名相同
        6) 函数的实现

#include <iostream>

//定义一个名叫sum的函数
int  sum(int n) {
	int s = 0;

	for(int i=1; i<=n; i++) {
		s += i; // s = s + i;
	}
	
	return s;
}


int main(void) {
	// 1+2+3+...+50 = ?
	std::cout << sum(10) << std::endl;

	// 1+2+3+...+100 = ?
	std::cout << sum(100) <<std::endl;

	system("pause");
	return 0}

    

函数的调用和声明

实参和形参:
    函数调用时, 实参的值, 传递给形参.
    即, 形参被赋值为实参.

    
函数声明\函数定义\函数调用的顺序
在这里插入图片描述

    

函数参数的传递方式

调用函数时,形参被赋值为对应的实参,
实参本身不会受到函数的影响!

在这里插入图片描述

    

使用数组作为函数参数

#include <iostream>
#include <Windows.h>

using namespace std;

void scorePrint(int score[], int n) {
	for (int i=0; i<n; i++) {
		cout << "第" << i+1 << "门成绩 : " << score[i] << endl;
	}
}

//每个成绩加5分
void scoreAdd(int score[], int n, int val) {
	for (int i=0; i<n; i++) {
		score[i] += val;
	}
}

int main(void) {
	int score[3] = {60, 70, 80};

	scorePrint(score, 3);
	scoreAdd(score, 3, 5);
	scorePrint(score, 3);

	system("pause");
	return 0;
}

    

默认参数

注意: C语言不支持函数的默认参数!,C++才支持

//每个成绩加5分
// 默认参数, 只能出现在参数列表的最后, 即默认参数后面, 不能有普通参数
//默认参数在函数调用时可以省略不写,例如:scoreAdd2(score,n);
void scoreAdd2(int score[], int n, int val=5) {
	for (int i=0; i<n; i++) {
		score[i] += val;
	}
}

    

同名不同命之函数的重载

C语言的每一个函数必须是不同函数名
C++可以使用同名函数[重载函数]实现功能类似的多个不同函数.

int add(int a, int b) {
	cout << "调用add版本1" << endl;
	return a +b;
}

float add(float a,   float b) {
	cout << "调用add版本2" << endl;
	return a+b;
}

函数名重载:
    函数名相同,
    但是, 函数的参数(形参)绝不相同:
        1)参数个数不同
        2)或参数个数相同, 但是参数的类型不同

    只有返回类型不同,不能构成函数重载
    只有形参变量名不同, 不能构成函数重载.

注意: C语言不支持函数重载

    

函数的栈空间

要避免栈空间溢出。
当调用一个函数时,就会在栈空间,为这个函数,分配一块内存区域,
这块内存区域,专门给这个函数使用。
这块内存区域,就叫做“栈帧”。
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <Windows.h>

void test(void) {
	//运行时将因为栈帧空间溢出,而崩溃
	char buff[2000000];  //大约2G内存,而栈一般只有2M大小
	std::cout << (int)buff[sizeof(buff) - 1] <<std::endl;
}

int main(void) {
	test();
	system("pause");
	return 0;
}

    

极速调用之内联函数

函数的作用:
避免重复制造轮子。
(避免重复多次写相同的代码)

函数的缺点:
每调用一次函数,就会为这个函数分配一个“栈”,
在计算机底层做很多准备工作(保护原来的执行环境,切换到新的执行环境)
有一定的“时间开销”

解决方案:
使用内联函数

内联函数:
当编译器在编译时, 如果遇到内联函数,
就会直接将整个函数体的代码插入”调用处”,
就相当于内联函数的函数体, 在调用处被重写了一次。
以避免函数调用的开销, 获得更快的时间。

内联函数的缺点:
使调用内联函数的程序,变得“臃肿”,消耗调用函数的“栈”空间。

内联函数的用法:

inline int add(int a, int b)
{
   return a + b;
} 

内联函数的使用场合:
1)内联函数中的代码应该只是很简单、执行很快的几条语句。
2)这个函数的使用频度非常高,比如在一个循环中被千万次地使用。

    

递归函数

定义:在函数的内部,直接或者间接的调用自己。

要点:
再定义递归函数时,一定要确定一个“结束条件”!!!

使用场合:
处理一些特别复杂的问题,难以直接解决。
但是,可以有办法把这个问题变得更简单(转换成一个更简单的问题)。

在这里插入图片描述

/*
	斐波那契数列
	1,1, 2,  3, 5, 8, 13, 21, .... 
	计算第n个数是多少?

	f(n) 
	当n >2时,f(n) = f(n-1) + f(n-2)
	当n=1或n=2时, f(n)就是1

	f(8) = f(7) + f(6)
*/
int  fib(int n) {
	int  s;
	
	if (n == 1|| n == 2) {
	    return 1;
	}
	
	s = fib(n-1)  +  fib(n-2);
	return  s;
}

递归函数的缺点:
性能很低!!!
实际开发中, 极少使用!

发布了26 篇原创文章 · 获赞 3 · 访问量 1541

猜你喜欢

转载自blog.csdn.net/qq_34850023/article/details/104516594
今日推荐