C++语言程序设计基础课程笔记03
本文将介绍 C++ 中 函数的一般用法。函数又称为方法,是一段程序代码。由三部分组成,函数声明,函数定义 和 函数体。
- 函数定义包含函数返回值,函数名 和 形式参数(形参)列表
- 函数体中是一些语句。
- 函数声明, 写法和函数定义差不多,但是没有函数体。通常可以缺省,但是如果被调用,但函数定义还没有出现,需要在调用之前书写函数声明
例如:
// 函数声明
int add(int a, int b);
// 返回值, 函数名, 形参列表
int add(int a, int b) {
// 函数体
return a + b;
}
调用是可以被调用的, 调用时需要提供实际参数(实参)列表。
这里常量“cpp” 就是实参, name 就是形参
#include <iostream>
#include <string>
using namespace std;
int hi(string name) {
cout << "hi" << name << endl;
}
int main() {
cout << "1" << endl;
hi("cpp");
cout << "2" << endl;
}
语句按照顺序执行,遇到函数先执行函数内部,返回之后继续执行。
和大多数程序一样,函数可以嵌套,函数中又可以调用其他的函数。
而函数调用自身,称为递归,编写算法的时候经常使用递归。
unsigned fib(unsigned int n) {
if (n == 1) {
return 1;
}
if (n == 2) {
return 1;
}
return fib(n - 2) + fib(n - 1);
}
通常递归需要退出条件。
下面介绍一些要点 和特性, 实参形参和引用、constexpr、默认参数、函数重载
关于形参和实参,实参就是调用的时候填写的参数,当执行调用的时候,会发生实形结合。实形结合,就是形参会被分配内存空间,并且实参的值会传递给形参。定义的时候形参不占用内存空间。
参数传递有两种:
-
单项传递,也就是传值,这样函数内如果需要改变实参,就不行的,因为不在一个内存空间。那么需要通过双向传递来实现,
-
双向传递,就是传引用,需要把形参的类型设置为引用类型,那么实形结合的时候,会把形参的引用和实参的数据绑定,这个绑定关系不会改变,并且形参不占用内存空间。
引用 不是变量,是变量的别名,不占用内存空间,写法如下:
# 类型& 是一个引用类型
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
int main() {
int x = 1;
int y = 2;
swap(x, y);
cout << "x = " << x << ",y = " << y << endl;
}
那么 a 是一个引用类型 和 实参x的数据进行绑定,是x 的别名,通过双向传递,可以改变实参的值。
constexpr 是 c++ 中的一个关键字,可以添加到函数的定义或者声明开头,这个语法是一个比 const 更严格的语法
- 要求函数体的所有参数是 constexpr 时,返回值也是 constexpr
- 函数中只能有return语句
有什么用呢,总结来说,就是 constexp r要求编译时不可变(而 const 只是运行时不可变,编译时有可能值还没有确定,还是变量),即在编译时可以推导出来,这样严格约束,一方面描述这是一个常量表达式, 另外一方面可以在编译时进行优化。
默认参数,这个在python中是支持的,C++ 的写法类似,允许设置默认的参数,这样在调用时可以不提供某些实参,但是默认参数需要从右到左提供,不用都提供。例如:
int test1(int a , int b = 1, int c = 2); // ok
int test2(int a = 1, int b ) // error
如果函数声明中已经写了默认参数,函数定义中就不用写默认参数了。
函数重载(overload),是指一个相同名称的函数,通过参数数量和参数类型的不同,有多个版本的功能。例如:
int add(int a , int b);
double add(double a, double b);
需要注意的,重载是不支持返回值类型不同的。(因为隐式类型转换的存在,可能引起歧义)。虽然说好处的是可以用同一个方法名,反复使用,而不用使用addInt addDouble这样的名称。对于使用函数的人来说,需要注意的是,由于使用的参数不同,需要确定实际上是调用哪个方法。
总之,函数是编程中随处可见的操作,C++ 需要注意的就是参数传递和函数声明。
原文地址:https://www.cnblogs.com/shalk/p/13308508.html
- 如何使用Sentry管理Hive外部表(补充)
- WebLogic XMLDecoder反序列化漏洞(CVE-2017-10271)漏洞复现&修复方案
- 如何在CDSW中使用R绘制直方图
- CTF学习交流群 第一期入群题writeup大放送
- 如何使用Hue创建Spark1和Spark2的Oozie工作流
- 【译】深入研究 Laravel 的依赖注入容器
- 一次XSS突破的探险
- 如何使用Hue创建Spark2的Oozie工作流(补充)
- 如何基于CDSW基础镜像定制Docker
- OVSDB介绍及在OpenDaylight中的调用
- 如何在CDH集群的非元数据库节点安装MySQL5.7.12
- PySpark数据类型转换异常分析
- SQLI-LABS 更新帖(二)
- 如何重置Hue用户密码
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 教你设计一个超牛逼的本地缓存!
- Flutter延时任务、Flutter通过Future与Timer实现延时任务
- DDIA 笔记
- 工作流和状态机
- CentOS 6.x 搭建:Headless Chrome + ChromeDriver + Selenium的爬虫环境系统
- 聊聊dubbo-go的registryAwareCluster
- 同样是空值,null和undefined有什么异同?
- 强大到没朋友的mysql-shell及插件
- android JavaPoet记录
- JavaScript里的分号,你加还是不加?
- 技术干货 | Docker 容器逃逸案例汇集
- 一张千万级别数据的表想做分页,如何优化?
- 一文学会爬虫技巧
- 为什么机器学习应用交易那么难(中)
- 消息队列的消费幂等性如何保证