Lesson 01-学习笔记-C++入门(缺省函数、函数重载、引用)

Lesson 01-学习笔记-C++入门(缺省函数、函数重载、引用),第1张

Lesson 01-学习笔记-C++入门(缺省函数、函数重载、引用)

C++入门

缺省参数

*1.缺省参数的概念**2.缺省参数的分类* 函数重载

*1.函数重载概念**2.C++支持重载的原理---名字修饰**3.extern "C"* 引用

*1.引用的概念**2.引用的特性**3.引用的应用*

缺省参数 1.缺省参数的概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

void Func(int a = 0)  //缺省值就是0
{
  cout << a << endl;
}

int main()
{
  Func();  //没有传参时,使用参数的默认值
  Func(1); //传参时,使用指定的实参
  
  renturn 0;
}
2.缺省参数的分类

一、全缺省参数:所有参数都给了缺省值

void Func(int a = 1,int b = 2,int c = 3)  //三个参数都有默认值,也就是缺省值
{
  cout << "a = " << a << endl;
  cout << "b = " << b << endl;
  cout << "c = " << c << endl << endl;
}

int main()
{
  Func();  //不传参,输出结果就是 1,2,3
  Func(10);  //只传了一个实参,从左往右传,输出结果就是 10,2,3
  Func(10,20);  //传了两个实参,输出结果就是 10,20,3
  Func(10,20,30);  //传了三个实参,输出结果是 10,20,30
  
  renturn 0;
}

这里注意,只传一个参数时,会默认是从左往右传,所以不会出现只传给b或者c,也不会出现只传b和c。

二、半缺省参数:缺省部分参数,且必须从右往左缺省

void Func(int a,int b = 2,int c = 3)  //只有b和c有缺省值
{
  cout << "a = " << a << endl;
  cout << "b = " << b << endl;
  cout << "c = " << c << endl << endl;
}

int main()
{
  Func(10);  //只传了一个实参,从左往右传,输出结果就是 10,2,3
  Func(10,20);  //传了两个实参,输出结果就是 10,20,3
  Func(10,20,30);  //传了三个实参,输出结果是 10,20,30
  renturn 0;
}

这里注意,缺省参数只能从右往左缺省,且必须连续缺省,不能间隔给。传参时还是默认从左往右传,而且至少要传一个参数,不能没有实参。

注意:
1.缺省参数不能在函数声明和定义中同时出现(要么在声明,要么在定义,推荐写在声明里)
2.缺省值必须是常量或者全局变量
3.C语言不支持

函数重载 1.函数重载概念

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)不同,常用来处理实现功能类似数据不同的问题。

#include
using namespace std;

//1.参数类型不同
int Add(int left,int right)
{
  cout << "int Add(int left,int right)" << endl;
  return left + right;
}
double Add(double left,double right)
{
  cout << "double(double left,double right)" << endl;
  return left + right;
}

//2.参数个数不同
void f()
{
  cout << "f()" << endl;
}
void f(int a)
{
  cout << "f(int a)" << endl;
}

//3.参数顺序不同
void f(int a,char b)
{
  cout << "f(int a,char b)" << endl;
}
void f(char b,int a)
{
  cout << "f(char b,int a)" << endl;
}

int main()
{
  Add(1,2);
  Add(1.1,2.2);

  f();
  f(1);

  f(1,'a');
  f('a',1);

  return 0;
}

注意:
1.返回值不同,不能构成重载,因为调用的时候不能区分。
2.缺省值不同,不能够成重载。
3.有一种情况:一个无参,一个带参,如图
他构成重载,但是使用时会有问题,传参的话还好,如果不传参,调用就会出现歧义(二义性),不知道调用的是第一个还是第二个,所以会报错。

2.C++支持重载的原理—名字修饰

为什么C语言不支持重载,C++支持重载?C++是如何支持重载的?
在C/C++中,一个程序运行起来要经历几个阶段:预处理、编译、汇编、链接。

C语言不支持函数重载,因为编译的时候,两个重载函数的函数名相同,在func.o符号表中存在歧义和冲突,其次链接的时候也存在歧义和冲突,因为他们都是直接使用函数名去标识和查找,而重载函数,函数名相同。
而C++的目标文件符号表中不是直接用函数名来标识和查找函数,而是通过函数修饰规则来区分。
1、函数名修饰规则,但是这个修饰规则不同的编译器下不同:Linux下(g++)是_Z+函数名长度+函数名+参数首字母。
2、有了函数名修饰规则,只要参数不同,func.o的符号表里面重载的函数就不存在二义性和冲突了。
3、链接的时候,test.o的main的函数里面去调用两个重载的函数,查找地址时,也是明确。

3.extern “C”

有些时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern"C",意思是告诉编译器,将该函数按照C语言的规则来编译。

引用 1.引用的概念

引用不是新定义一个变量,而是给已经存在的变量取了一个别名,编译器不会为引用变量开辟内存空间,他和他的引用变量共用同一块内存空间。

类型&引用变量名(对象名)=引用实体:

void TestRef()
{
  int a = 10;
  int& ra = a;  //定义引用类型

  printf("%pn",a);
  printf("%pn",&ra);
}

注意,引用类型必须和引用实体是同种类型的。

2.引用的特性

1、引用在定义时必须初始化
2、一个变量可以有多个引用
3、引用一旦引用一个实体,则不能再引用其他实体

void TestRef()
{
  int a = 10;
  //int& b;  //该语句编译时会出错,必须要初始化
  int& b = a;
  int& c = a;
  int& d = b;
//类似一个人有多个名字,多个代号
  printf("%pn",a);
  printf("%pn",&b);
  printf("%pn",&c);
  printf("%pn",&d);
//运行结果都一样
}

还有这种情况:

int a = 10;
int& b = a;
int c = 20;
b = c;  //这里是把c赋值给b,而不是让b变成c的别名
3.引用的应用

1、做参数

void Swap(int& a, int& b)
{
  int tmp = a;
  a = b;
  b = tmp;
}

int main()
{
  int x = 0, y = 1;
  Swap(x,y);
  return 0;
}

2、引用做返回值

一、传值返回值

int Add(int a, int b)
{
  int c = a + b;
  return c;
}

int main()
{
  int ret = Add(1,2);
  cout << ret << endl;
  
  return 0;
}


临时变量存在于:
1、如果c比较小,则一般是寄存器充当变量
2、如果c比较大,临时变量放在调用Add函数的栈帧中
所有的传值返回都会生成一个拷贝

二、传引用返回值

int& Add(int a, int b)
{
  int c = a + b;
  return c;
}

int main()
{
  int ret = Add(1,2);
  cout << ret << endl;
  
  return 0;
}


当前代码的问题是:
1、存在非法访问,因为Add(1,2)的返回值是c的引用,所以Add栈帧销毁了以后,会去访问c位置空间。
2、如果Add函数栈帧销毁,清理空间,那么取c值的时候取到的就是随机值,给ret的就是随机值,当前这个取决于编译器的实现了
ps:vs下销毁栈帧没有清空间数据

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5702683.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存