或许有一天c++系列能全部更新完,但是这里才是我写c++笔记的起点,本人也是边学边写,理解方面肯定会有很多问题存在,会尽量慢慢琢磨修改,有问题的地方也希望大家批评指出。
参考书目《C++ primer plus》
《C++语言程序设计 郑莉》
《C++语言描述,数据结构与算法》
- 综述:函数是模块划分的基本单位,在面向过程程序设计中,函数是某一过程的抽象,在面向对象程序设计中,函数是某一功能的抽象,函数编写好后只关心函数的功能而不关心函数的内容,有利于分工合作和开发效率
函数的定义和使用
- 函数是一个子程序,是程序块,main函数是程序执行的开始点,函数之间可相互调用。
- 可结合程序的机器级表示学习函数调用的底层知识
函数的定义
return_value fun_name(parameter){
body
}
😈 形式参数表(parameter)
复制构造函数&析构函数
什么是表?不是形容人的,而是用逗号分开的序列
- 形参是主调函数和被调函数的联系,
- 命令行参数:main函数的形参,作为操作系统启动程序时初始化
- 形参被称为傀儡,在没有调用时就是一个符号,只有调用后才能由主调函数将实际参数赋予形参
😈 函数的返回值和返回值类型
1 结束当前函数的执行
2 函数的返回值由return语句给出
3 也可以不带返回值,函数仅仅实现一种操作
函数的调用
函数名(实参表)
😈 函数的原型(函数声明)
返回值 函数名(形参表);
函数声明不会产生任何代码,只是将函数的有关信息告诉编译器
编译器根据函数原型对函数调用进行检查,判断是否符合要求。
- 实参和形参相对应
- 函数作为参数进行调用
⭐实例:将二进制转化为十进制
#include<iostream>
double power(double x, int n);
using namespace std;
int main() {
cout << "Please enter an 8 bit binary number:";
int dem = 0;
for (int i = 7; i >=0; i--) {
char bit;
cin >> bit;
if(bit=='1')
dem += power(2, i);
}
cout << "Decimal value is " << dem << endl;
return 0;
}
double power(double x, int n) {
double result = 1;
for (int i = 1; i <= n; i++) {
result *= x;
}
return result;
}
针对本程序的一些解释
- 为什么选择输入char类型,插入类型一次只读入一个字符,如果我们按int类型输入相应位,就需要用换行或空格的方式告诉程序此次输入结束,当我们使用char类型,输入一串位串后,输入流里就存在这些数字,一次只读取一个数字,即使输入很多,也会按从左往右的顺序按位读取(与输入流有关的知识会专门写博客讲解)
- 注意到在结果相加之前有个判断语句
if(bit=='1')
,如果我们直接使用dem+=bit*power(2,i);
会出现错误,这里bit会按照int类型解释,就会将其ASCII码作为bit的值。
⭐实例:将一个数翻转
bool judge(int x) {
int m = 0;
int n = x;
while (x > 0) {
m = m * 10 + x % 10;
x /= 10;
}
return m == n;
}
⭐实例:随机数:投骰子的随机游戏
- 随机函数:
int rand(void)
产生伪随机数,按照一个既定的序列产生数字,rand函数需要一个称为种子的初始值,不同的种子随机数序列不同,不设置种子其默认值为1,调用函数void srand (unsigned int seed)
为其设置种子。 - 产生随机数需要头文件
#include<cstdlib>
程序设计的过程
审题分析→设计算法→写程序
嵌套调用
递归调用
- 将问题进行分简,出现的新问题是原有问题简化的子集
- 只有有限的阶乘才有意义
- 递归的过程
1 递推:将问题分解为子问题,从未知向已知推进,达到已知的条件
2 回归:根据递归过程逐一求值回归
⭐实例:用递归法计算从n个人中选择k个人组成一个委员会的不同组合数
从n个人里面选k个人=从n-1个人里面选k-1个人+从n-1个人里面选k个人
⭐经典实例:汉诺塔问题
函数的参数传递
- 形参:函数未被调用时,形参不具有实际空间和实际的值,函数调用时将实参和形参结合
😈 形实结合(可结合计算机系统系列过程部分讲解)
⭐值传递
当函数调用时,为形参分配内存空间,并用实参初始化形参,单向传递。形参的值变化对实参不起作用
⭐引用传递
引用是一种特殊类型的变量,被认为是另一个变量的别名
int i,j;
int &ri=i;
- 声明引用时,必须对其进行初始化,使它指向一个已存在的对象
- 一旦引用被初始化,就不能指向其他对象
引用一旦诞生,就确定了一个对象,且一生只为一个对象
⭐实例:交换数值
#include<iostream>
using namespace std;
void swap(int &x, int & y);
int main() {
int x = 10, y = 5;
int &rx = x;
int &ry = y;//也可以不定义引用,直接在函数原型和定义中说明引用类型,可直接转换为引用
swap(rx, ry);
cout << x << " " << y;
return 0;
}
void swap(int &x, int &y) { //参数为引用类型
int temp;
temp = x;
x = y;
y = temp;
return;
}
内联函数
函数调用可提高开发效率,分块解决问题,但是函数调用降低程序执行效率(尤其是递归函数),对于一些内容简单的函数,调用函数的成本比使用函数内容的成本高得多
- 内联函数:内联函数不是执行时调用,而是在编译时直接嵌入对应的调用处,节省了参数传递,控制转移等开销(但是对于现在的编译器,有了优化系统,没有设置inline的函数也可能被编译为内联,过于冗杂的函数可能被编译器优化为一般函数)
- 通俗来讲,与其每次为了见小鬼去全国各地看他的演唱会,不如直接把他拐到家里,省了路费和精力消耗。
inline return_type fun_name(parameter){body}
- 以空间换时间,短小精干
- 引用不是对象,引用并没有在程序中占据内存空间,故没有地址的说法.
含可变参数的函数
- 可变长度的形参表
- 当实参类型都相同时,可以使用initializer_list
initializer_list<string>ls;
带默认参数值的函数
int add(int x=10,int y=6){
return x+y;
}
int main(){
int z=add(5);
int p=add(2,6);
return;
}
- 有实参则用实参,无实参则用默认值
- 有默认参数的形参在后边,赋值所用实参先赋给列表前面
- 如果有函数原型,在函数原型中提供了默认值,在函数定义中不能有默认值,如果没有函数原型,在定义中确定默认值
先写到这里吧,随后根据primer plus上的内容再进行补充