C++ 教程 - 03 函数篇

文章目录

  • 函数定义
  • 函数案例
  • 作用域
  • 函数传参
  • 函数返回值
  • 函数返回数组

函数定义

  • 函数是将一部分代码进行封装,便于重用、维护,使得代码更加的整洁。

  • 定义函数格式
    类型 函数名(形参类型 形参名称,…){ 函数体; return 类型值;}

  • 函数调用使用 函数名(实参),传入实参个数和类型要与形参对应;类型不匹配时,会隐式转换,若无法转换,则报错;

  • 函数定义代码

// 求和
int sum(int a, int b){int c = a + b; //return c;
}

函数案例

  • 2 10 {2^{10}} 210 的值;->1024
// pow 函数可以求幂运算
int calc(int base, int exponential){return pow(base, exponential);
}

 

  • 输入一个非负整数n,求n的阶乘;
// 递归
int calcFactorial(int n) {if (n == 0 || n == 1) {return 1;   // 有明确的返回条件}return n * calcFactorial(n - 1); // 递归  函数调用自身
}// 入口函数
int main() {cout << calcFactorial(6) << endl;return 0;
}

 

  • 输入一个非负整数n,求1-> n的斐波那契数列;
    • n为0、1时,f(n) = 1;
    • f ( n ) = f ( n − 1 ) + f ( n − 2 ) ; n > = 2 f(n) = f(n-1) + f(n-2);n>= 2 f(n)=f(n1)+f(n2);n>=2,即从第三项开始,每一项均为前两项之和。
    • 递归思想,函数调用自身且函数有明确的返回条件;
// 计算斐波那契每一项的值
int calcFibonacci(int n) {if (n == 0 || n == 1) {return 1;}return calcFibonacci(n - 1) + calcFibonacci(n - 2);
}// void 表示无返回值
void outputValue(int n) {// cout 输出到控制台  << 流输出运算符cout << calcFibonacci(n)<< " ";
}// 入口函数
int main() {cout << "输入一个自然数:" << endl;// 控制台输入  >> 流输入运算符int n;cin >> n;// 循环输出n以内的斐波那契数列for (int i = 0; i <= n; i++) {outputValue(i);}return 0;
}

 

作用域

  • 函数内的变量及形参都是局部变量,只在函数内部可以使用;
  • 函数外部的变量为全局变量,全局可以使用,其他源文件也可以引用;
  • static 修饰的局部变量为局部静态对象(默认初始化为0),函数每次压栈执行时,静态对象的值不会重置; 而局部变量在函数每次压栈执行时创建,返回出栈时销毁;
  • static 修饰的全局变量为全局静态对象,只能在本源文件中使用;
// 统计一个函数被调用的次数
int callTime(int p) {static int times; // 静态对象 默认初始化为0; 而局部变量(自动对象,存在栈中)必须自己初始化;times++;return times;
}
  • 如果函数在调用时,在此之前的代码中尚未定义,则必须先声明该函数,才可以调用;
    • 如 int callTime(int p); 为函数声明,去掉函数体;
    • 形参名也可以省略;
  • 在a.cpp源文件中定义一个函数F,可以在b.cpp中调用,调用前只需简单声明即可;c.app中要调用该函数也需要提前声明;
  • 为了避免多次调用需多次声明,可以创建一个头文件,并在该头文件中声明一次,其他源文件包含该头文件即可;
    在这里插入图片描述
// a.cpp
#include <string>
using namespace std;string getName() {string name = "jack";return name;
}// lauf.h 头文件
#pragma once  // 仅编译一次
#include <string>
using namespace std;// 函数声明
string getName();// b.cpp  包含头文件,并调用函数
#include <iostream>
#include "lauf.h" // 包含自定义的头文件
using namespace std;// 入口函数
int main() {cout << getName() << endl; // 直接调用函数return 0;
}

 

函数传参

  • 值传递,实参的值拷贝一份,给形参; 实参、形参互不影响;
  • 引用传递,将实参的别名传给形参,实参、形参指向同一地址;
bool cmpStr(string str1, string str2){ // 值传递return str1.size() > str2.size();
}bool cmpStr(string& str1, string& str2){ // 引用 别名  传递return str1.size() > str2.size();
}// 尽量使用常量引用 作为形参
bool cmpStr(const string& str1, const string& str2){ // 常量引用  传递return str1.size() > str2.size();
}// 调用时,传入实参  形式相同
string s1 = "jack";
string s2 = "tom";
cmpStr(s1, s2);  // 传值 还是传引用  取决于形参类型
  • 数组传递,数组不允许直接拷贝
    • void operateArr(const int arr[ ], int size){}; 实参传入数组名(首地址)
    • void operateArr(const int* ptr, int size){}; 实参传入数组名;
    • void operateArr(const int(& arr)[10]){}; 实参传入数组名,进行数组的引用;
// 数组拷贝
#include <iostream>
#include "lauf.h" // 包含自定义的头文件
using namespace std;void printArray(const int arr[], int size) { // 数组无法直接拷贝; 故函数内部无法使用sizeof计算数组的大小,所以必须传入数组的大小;for (int i = 0; i < size; i++) {cout << arr[i] << endl;}}// 入口函数
int main() {// 定义一个数组, 常量指定长度int arr[5] = { 1, 2, 1, 3, 4 };printArray(arr, 5);  // 数组无法直接拷贝return 0;
}// 数组引用
#include <iostream>
#include "lauf.h" // 包含自定义的头文件
using namespace std;void printArray(int(&arr)[5]) { // 必须指定长度for (int i : arr) {cout << i << endl;}}// 入口函数
int main() {// 定义一个数组, 常量指定长度int arr[5] = { 1, 2, 1, 3, 4 };printArray(arr);return 0;
}// *********************
// 修改数组的值
#include <iostream>
#include "lauf.h" // 包含自定义的头文件
using namespace std;void modifyArray(int (&arr)[5]) { // 必须指定长度// 引用数组  可以使用sizeof 计算大小int size = sizeof(arr) / sizeof(arr[0]);cout << size << endl;for (int i = 0; i < size; i++) {// 修改数组的值arr[i] = pow(arr[i], 2);}for (int e : arr) {cout << e << endl;}
}// 入口函数
int main() {// 定义一个数组, 常量指定长度int arr[5] = { 1, 2, 1, 3, 4 };modifyArray(arr);return 0;
}

 

函数返回值

  • 无返回值 void类型;
void func(int a, int b){int c = a + b;return;  // 无返回值  return 可以省略
}
  • 有返回值
// 返回值的拷贝
string func(const string& name){return name;  // 这里返回 name值的拷贝;
}// 返回 值的引用
const string & func(const string& name){return name;  // 这里不会拷贝name的值,而是直接返回对其的引用(高效)
}

 

函数返回数组

  • 方式1,指针形式
// 方式1 
int* func(int n, int size) {// 动态分配数组,使用newint* arr = new int[size];  // 使用完成后 必须delete[] arr 释放for (int i = 0; i < size; i++) {// 数组赋值arr[i] = pow(i, 2); // 取平方}return arr;  // 返回数组首地址
}// 入口函数
int main() {// 指定数组的长度int size = 5;int* p = func(10, size); //  调用函数, 返回数组// 输出for (int i = 0; i < size; i++) {cout << *(p + i) << endl; // 指针偏移,并解引用}delete[] p;// 删除 堆内存 中的空间return 0;
}

-方式2,typedef 定义数组类型别名

#include <iostream>
#include "lauf.h" // 包含自定义的头文件
using namespace std;// typedef 定义类型别名
typedef int lauf[5]; // 声明一个 长度为10的int数组  lauf类型
int arr[5] = { 1, 3, 5, 1, 6 }; // 全局变量 形式
// 定义返回 数组指针 的函数
lauf* func(int n) {return &arr;  // 返回数组的地址,如果函数内部int arr[5] = { 1, 3, 5, 1, 6 };初始化数组,则函数执行结束弹栈(数组变量存在栈内存),数组内存被释放,再通过首地址取值就会出错!!!// 必须使用static修饰// static int arr[5] = {1,3,5,1,6}; // 静态数组对象,放入全局数据区,函数结束弹栈不会释放数组空间;
}// 入口函数
int main() {// 声明 数组指针 变量 int(*p)[5] = func(5); //  调用函数, 返回 数组指针// 输出for (int i = 0; i < 5; i++) {cout << *(*p + i) << endl;  // *p 解引用到arr的首地址}return 0;
}
  • 方式3, 数组指针 类型后缀形式
#include <iostream>
#include "lauf.h" // 包含自定义的头文件
using namespace std;// 后置类型
auto func(int n)->int(*)[5]  {//int arr[5] = { 1, 3, 5, 1, 6 };  这种形式,函数执行结束会释放数组空间;static int arr[5] = {1,2,5,1,6}; // 静态数组对象,放入全局数据区,函数结束弹栈不会释放数组空间;return &arr;  // 返回数组的地址
}// 入口函数
int main() {// 声明 数组指针 变量 int(*p)[5] = func(5); //  调用函数, 返回 数组指针// 输出for (int i = 0; i < 5; i++) {cout << *(*p + i) << endl;  // *p 解引用到arr的地址}return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/284016.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

劲松中西医结合医院主任谭巍谈生殖感染对夫妻的四大影响

生殖感染对健康的影响很大&#xff0c;夫妻若有一方发生生殖感染问题&#xff0c;那么极有可能将这种健康问题感染给另一方。所以生殖感染对夫妻双方都可能产生不良影响。 提到生殖感染对夫妻关系的影响&#xff0c;劲松中西医结合医院主任谭巍认为生殖感染不仅会对患者的身体…

javaWebssh课堂点名管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh课堂点名管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。开发环境为TOMCAT7.…

低代码工作流,在业务场景下启动流程节点绑定的具体步骤与注意事项

在业务管理的场景下&#xff0c;存在先做了对应的数据管理&#xff0c;后续增加管理的规范度&#xff0c;“在业务数据变化时发起流程”的需求&#xff0c;那么这种情况下就需要在业务管理&#xff08;列表页、表单&#xff09;中发起流程&#xff0c;让业务模型使用流程配置&a…

《数据结构、算法与应用C++语言描述》-最大高度优先左高树-C++实现

左高树 完整可编译运行代码见&#xff1a;Github::Data-Structures-Algorithms-and-Applications/_26maxHblt 定义 (大顶堆和小顶堆)堆结构是一种隐式数据结构(implicit data structure)。用完全二叉树表示的堆在数组中是隐式存储的(即没有明确的指针或其他数据能够用来重塑…

Linux常用网络指令

网络参数设定使用的指令 手动/自动设定与启动/关闭 IP 参数&#xff1a;ifconfig, ifup, ifdown ifconfig ifconfig常用于修改网络配置以及查看网络参数的指令 [rootwww ~]# ifconfig {interface} {up|down} < 观察与启动接口 [rootwww ~]# ifconfig interface {options…

Windows如何安装使用TortoiseSVN客户端并实现公网访问本地SVN Server

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

备忘录可以设置闹钟提醒吗怎么设置

虽然很多人都有使用备忘录的习惯&#xff0c;将待办事项一一记录下来&#xff0c;但单纯的记录并不足以保证我们不会忘记。尤其是那些不经常查看备忘录的人&#xff0c;可能会错过一些重要的信息。这就是为什么备忘录需要带闹钟提醒功能的原因。 带闹钟提醒的备忘录就像是一个…

CRM如何帮助中小微企业优化销售、营销和客服

CRM系统的一大价值就是分析。CRM系统沉淀着大量数据。将这些数据呈现出来&#xff0c;并进行数据挖掘和辅助决策&#xff0c;是判断CRM系统是否具有商业智能的分水岭。下面我们就来聊聊&#xff0c;CRM如何帮助中小微企业进行统计分析。 CRM包括客户管理、线索管理、商机管理、…

python 实现 AIGC 大模型中的概率论:生日问题的公式推导

在前两节中&#xff0c;我们推导了生日问题的求解算法&#xff0c;但在数学上的最终目标就是希望能针对问题推导出一个简洁漂亮的公式&#xff0c;就像爱因斯坦著名的质能方程 E MC^2 那样&#xff0c;毕竟数学是以符号逻辑来看待世界本质的语言&#xff0c;所以絮絮叨叨不是数…

codeforces D. Cyclic MEX

思路 手模发现把第一个 x x x 移到最末尾时&#xff0c;进入队列吐出大于等于 x x x 的&#xff0c;保留小于 x x x 的。模拟此过程。如果队列里存 n n n 个数的话&#xff0c;那么时间复杂度达到 n 2 n^2 n2 不可取。所以队列存储 ( x , f x ) (x,\;f_x) (x,fx​) 大小及…

✺ch4——管理3D图形数据

目录 缓冲区和顶点属性统一变量顶点属性插值应用变换矩阵一个3D立方体示例渲染一个对象的多个副本——实例化在同一场景中渲染多个不同模型矩阵栈应对“Z冲突”伪影图元的其他选项性能优先的编程方法 使用 OpenGL 渲染 3D 图形通常需要将若干数据集发送给 OpenGL 着色器管线。举…

中小型企业网络综合实战案例分享

实验背景 某公司总部在厦门&#xff0c;北京、上海都有分部&#xff0c;网络结构如图所示&#xff1a; 一、网络连接描述&#xff1a; 厦门总部&#xff1a;内部网络使用SW1、SW2、SW3三台交换机&#xff0c;SW1为作为核心交换机&#xff0c;SW2、SW3作为接入层交换机&#x…