缺省和重载。引用——初识c++

在这里插入图片描述
在这里插入图片描述

.

个人主页:晓风飞
专栏:数据结构|Linux|C语言
路漫漫其修远兮,吾将上下而求索


文章目录

  • C++输入&输出
  • cout 和cin
    • <<
    • >>
  • 缺省参数
    • 全缺省
    • 半缺省
      • 应用场景
      • 声明和定义分离的情况
  • 函数重载
    • 1.参数的类型不同
    • 2.参数的个数不同
    • 3.参数的顺序不同(本质还是类型不同)
  • C++支持函数重载的原理--名字修饰(name Mangling)
    • Linux编译器的命名规则
  • 引用
    • 引用概念
    • 引用特性
    • 引用的作用
      • 1.作为参数(输出型参数)
      • 2. 做返回值
      • 2.对象比较大,减少拷贝,提高效率
    • 指针和引用的区别


C++输入&输出

cout 和cin

在这里插入图片描述

<<

这里的c意思是console,把数据out到console(控制台)中去,而最后面的endl其实等价与\n,就是换行

在这里插入图片描述

>>

同样的道理cin,把数据in到console(控制台),也就是输入数据到控制台中。

在这里插入图片描述

1.使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件
以及按命名空间使用方法使用std。
2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< 
iostream >头文件中。
3. <<是流插入运算符,>>是流提取运算符。
4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。
C++的输入输出可以自动识别变量类型。
5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,

缺省参数

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

全缺省

#include<iostream>
using namespace::std;

void Func(int a = 10 , int b = 20 , int c =30)
{
  cout << "a:" << a << endl;
  cout << "b:" << b << endl;
  cout << "c:" << c << endl << endl;
}


int main()
{
// 没有传参时,使用参数的默认值
// 传参时,使用指定的实参
  Func(1,2,3);
  Func(1,2);
  Func(1);
  Func();
  return 0;
}

在这里插入图片描述

那么可不可以隔着一个数传参呢?答案是不能
在这里插入图片描述

半缺省

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现
#include<iostream>
using namespace::std;

//半缺省参数从右往左依次给出
//半缺省参数不是缺少一半,而是有缺少就是半缺省
void Func(int a , int b = 20 , int c =30)
{
  cout << "a:" << a << endl;
  cout << "b:" << b << endl;
  cout << "c:" << c << endl << endl;
}

int main()
{
  Func(1,2,3);
  Func(1,2);
  Func(1);

  return 0;
}

应用场景

假如我有一个栈,但是不知道要插入多少数据,目前栈的空间是固定的,怎么解决数据的容量问题?

struct stack
{
  int* a;
  int size;
  int capacity;
};

void stackInit(stack* ps)
{
  //容量固定
  ps->a = (int*)malloc(sizeof(int) * 4);
}

void StackPush(stack* ps,int x)
{
}

int main()
{
  //不知道要插入多少个数据
}

用半缺省参数就可以很好的解决这个问题
在这里插入图片描述

声明和定义分离的情况

在声明和定义分离的情况下,那么是在声明处缺省,还是在定义处缺省呢?

//stack.h头文件下的定义
void stackInit(struct stack* ps, int n = 4);

//stack.cpp下的声明
void stackInit(struct stack* ps, int n)
{
    ps->a = (int*)malloc(sizeof(int) * n);
}

应该在头文件下的定义处缺省,因为在运行时,要包含的是头文件,程序在编译的时候会展开头文件,这时候就可以进行缺省调用。而且在声明处还可以判断语法是否正确
如果在定义处缺省,那么在第3个情况下就会出现参数太少的报错情况,达不到缺省。

在这里插入图片描述

如果声名与定义位置同时出现缺省,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。出现重定义报错

在这里插入图片描述

函数重载

c语言不允许同名函数
c++可以,要求,函数名可以相同,但是参数不同,构成函数重载 ,并且会对数据类型自动匹配。

1.参数的类型不同

在这里插入图片描述

2.参数的个数不同

在这里插入图片描述

3.参数的顺序不同(本质还是类型不同)

在这里插入图片描述
c语言不支持重载,链接时,直接用函数名去找地址,有同名函数,区分不开。
那么C++是怎么支持的呢?

C++支持函数重载的原理–名字修饰(name Mangling)

函数名修饰规则,名字中引入参数类型,各个编译器自己实现了一套

Linux编译器的命名规则

因为Linux的规则比较简单,我们先理解一下Linux编译器的规则
在这里插入图片描述
在这里插入图片描述
解释:如果是Add这样的前面就是_Z3,f就是_Z1,后面就都是加上函数名字和数据类型的首字母

正是用类似这样的规则给函数修饰名字,只要参数不同,修饰出来的名字就不一样,就支持了重载。这样链接的时候用这样的名字,就可以找到对应的函数地址

引用

引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空
间,它和它引用的变量共用同一块内存空间。
比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

int main()
{
  int a = 0;

  //引用,b就是a的别名
  int& b = a;

  cout << &a << endl;
  cout << &b << endl;
  return 0;
}

在这里插入图片描述
注意:引用类型必须和引用实体是同种类型的

引用特性

  1. 引用在定义时必须初始化
    在这里插入图片描述
  2. 一个变量可以有多个引用
    在这里插入图片描述
  3. 引用一旦引用一个实体,再不能引用其他实体
    在这里插入图片描述
    4.引用不能改变指向
    在这里插入图片描述

引用的作用

1.作为参数(输出型参数)

//指针传参
void Swap(int* a, int* b)
{
  int tmp;
  tmp = *a;
  *a = *b;
  *b = tmp;
}

//引用传参
void Swap(int &a , int &b)
{
  int tmp;
  tmp = a;
  a = b;
  b = tmp;
}

int main()
{
  int x = 0, y = 1;
  Swap(&x, &y);
  cout << "x=" << x << endl;
  cout << "y=" << y << endl;

  Swap(x, y);
  cout << "x=" << x << endl;
  cout << "y=" << y << endl;
}

这里a相当于x的别名,y相当于b

在这里插入图片描述

typedef struct Node
{
  struct Node* next;
  struct Node* prev;
}LNode,*Pnode;

void PushBack(Pnode& phead, int x);

void PushBack(struct LNode** phead, int x);
void PushBack(struct LNode*& phead, int x);

 
int main()
{
  Pnode plist = NULL;
  return 0;
}

这里*pnode 相当于struct Node*,Node相当于struct Node

2. 做返回值

int& func()
{
  int a = 0;
  return a;
}

int main()
{
  int ret = func();
  return 0;
}

这段代码意味着返回a别名,但是由于栈帧销毁,会造成野引用,这里的值是不确定的,取决于编译器,以及是否清内存。
在这里插入图片描述
在这里插入图片描述

可以看到这里随便调用了一个函数就导致结果变化,因为fxfunc相同,空间重复使用,所以在原来销毁的a的位置创建了b,所以导致输出来的值又a的6,变成了b的1。

小结:

返回变量出了函数作用域,生命周期就到了要销毁(局部变量),不能引用返回

那么怎么使用引用返回呢?

int& func()
{
  static int a = 6;
  return a;
}

int main()
{
  int &ret = func();
  cout << ret << endl;
  return 0;
}

这里加上一个static就可以。


int& Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int& ret = Add(1, 2);
    Add(3, 4);
    cout << "Add(1, 2) is :"<< ret <<endl;
    return 0;
}

在这里插入图片描述

#include<iostream>
using namespace std; 
#include<assert.h>

struct SeqList
{
  //成员变量
  int* a;
  int size;
  int cacpcity;

  //成员函数
  void Init()
  {
    a = (int*)malloc(sizeof(int) * 4);
    size = 0;
    cacpcity = 4;
  }

  void PushBack(int x)
  {
    //... 扩容
    a[size++] = x;
  }
  //临时变量有常性
  //读写返回变量
  int& Get(int pos)
  {
    assert(pos >= 0);
    assert(pos < size);

    return a[pos];
  }

};

int main()
{
  SeqList s;
  s.Init();
  s.PushBack(1);
  s.PushBack(2);
  s.PushBack(3);
  s.PushBack(4);

  for (int i = 0; i < s.size; i++)
  {
    cout << s.Get(i) << "";
  }
  cout << endl;

  for (int i = 0; i < s.size; i++)
  {
    if (s.Get(i) % 2 == 0)
    {
      s.Get(i) *= 2;
    }
  }
  cout << endl;
  for (int i = 0; i < s.size; i++)
  {
    cout << s.Get(i) << "";
  }
 }

2.对象比较大,减少拷贝,提高效率

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。这些效果指针也可以,但是引用效率更高

#include<iostream>
using namespace std;
#include <time.h>
struct A{ int a[10000]; };
void TestFunc1(A a){}
void TestFunc2(A& a){}
void main()
{
 A a;
 // 以值作为函数参数
 size_t begin1 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc1(a);
 size_t end1 = clock();
 // 以引用作为函数参数
 size_t begin2 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc2(a);
 size_t end2 = clock();
// 分别计算两个函数运行结束后的时间
 cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
 cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

在这里插入图片描述

指针和引用的区别

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

刷题记录:最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示例 2&#xff1a; 输…

慧天[HTWATER]软件:最好用的城市排水,数据处理软件

【城市内涝水文水动力模型介绍】 慧天[HTWATER]软件&#xff1a;慧天排水数字化分析平台针对城市排水系统基础设施数据管理的需求&#xff0c;以及水文、水力及水质模拟对数据的需求&#xff0c;实现了以数据库方式对相应数据的存储。可以对分流制排水系统及合流制排水系统进行…

如何让企微助手加粉更精准?

在当今数字化营销时代&#xff0c;无论是抖音平台上的广告投放&#xff0c;还是微信朋友圈的推广&#xff0c;其目的均是为了提升品牌曝光度和产品展示度。然而&#xff0c;更重要的是&#xff0c;广告的目的在于吸引潜在的目标客户&#xff0c;进而实现转化。在这个过程中&…

SHA加密

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

20240319-1-过拟合与欠拟合

过拟合欠拟合面试题 1. 如何理解高方差与低偏差? 模型的预测误差可以分解为三个部分: 偏差(bias)&#xff0c; 方差(variance) 和噪声(noise). 偏差 偏差度量了模型的期望预测与真实结果的偏离程度&#xff0c; 即刻画了学习算法本身的拟合能力。偏差则表现为在特定分布上…

Git基础(25):Cherry Pick合并指定commit id的提交

文章目录 前言指定commit id合并使用TortoiseGit执行cherry-pick命令 前言 开发中&#xff0c;我们会存在多个分支开发的情况&#xff0c;比如dev&#xff0c;test, prod分支&#xff0c;dev分支在开发新功能&#xff0c;prod作为生产分支已发布。如果某个时候&#xff0c;我们…

【MySQL】10. 复合查询(重点)

复合查询&#xff08;重点&#xff09; 前面我们讲解的mysql表的查询都是对一张表进行查询&#xff0c;在实际开发中这远远不够。 1. 基本查询回顾 数据还是使用之前的雇员信息表 在标题7的位置&#xff01; mysql> select * from emp where sal > 500 or job MANAG…

Unity数独完整源码

支持的Unity版本&#xff1a;2018.1或更高。 这是一套完整且高效的数独源码&#xff0c;默认是9x9&#xff0c;有上千种关卡文件&#xff0c;4种难度&#xff0c;内有关卡编辑器&#xff0c;可扩展至4x4、6x6的关卡&#xff0c;还有英文文档对源码各方面可配置的地方进行说明&…

静态住宅IP好用吗?怎么选择?

在进行海外 IP 代理时&#xff0c;了解动态住宅 IP 和静态住宅 IP 的区别以及如何选择合适的类型非常重要。本文将介绍精态住宅 IP 特点和&#xff0c;并提供选择建议&#xff0c;帮助您根据需求做出明智的决策。 静态住宅 IP 的特点 静态住宅 IP 是指 IP 地址在一段时间内保…

冒泡排序 快速排序 归并排序 其他排序

书接上回.. 目录 2.3 交换排序 2.3.1冒泡排序 2.3.2 快速排序 快速排序的优化: 快速排序非递归 2.4 归并排序 基本思想 归并排序非递归 海量数据的排序问题 排序算法时间空间复杂度和稳定性总结 四. 其他非基于比较排序 (了解) 2.3 交换排序 基本思想&#xff1a;…

GIS、CAD数据为基础进行城市排水系统水力建模方法

佳文推荐 城市内涝水文水动力模型介绍 在城市排水防涝规划过程中&#xff0c;水文水动力耦合模型已经成为一种不可或缺的分析工具。在模型建立、城市内涝风险评估、排水系统性能诊断以及海绵城市规划等方面&#xff0c;内涝耦合模型提供了相应的模拟及分析工具&#xff1a; …

C语言结构体之位段

位段&#xff08;节约内存&#xff09;&#xff0c;和王者段位联想记忆 位段是为了节约内存的。刚好和结构体相反。 那么什么是位段呢&#xff1f;我们现引入情景&#xff1a;我么如果要记录一个人是男是女&#xff0c;用数字0 1表示。我们发现只要一个bit内存就可以完成我们想…

Chrome浏览器修改网页内容

方法一&#xff1a;使用开发者工具 在Chrome浏览器中打开要修改的网页。按下F12键打开开发者工具。在开发者工具窗口中&#xff0c;找到“Elements”标签页。在“Elements”标签页中&#xff0c;找到要修改的网页元素。双击要修改的网页元素&#xff0c;即可进行编辑。 方法二…

C++ 之LeetCode刷题记录(四十)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 目标&#xff1a;执行用时击败90%以上使用 C 的用户。 27. 移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值…

【码云Git提交】Windows

一、第一次提交 1.登录码云创仓库 2.观察创建后的提示&#xff0c;就有步骤命令了 3.我们在系统中打开一个测试文件夹窗口打开GitBash PS&#xff1a;&#xff08;你需要提前装一个Node&#xff0c;本章不介绍&#xff09; 我们打开一个创建的test测试文件夹窗口&#xff0c;…

gif格式动图怎么制作?分享一种制作gif的方法

制作gif动图是非常有趣的&#xff0c;通过自制gif表情包能够丰富你的图片库&#xff0c;让你在社交平台上轻松的与朋友互动。那么&#xff0c;如何自己制作gif动画呢&#xff1f;很简单&#xff0c;通过使用gif图片制作&#xff08;https://www.gif.cn/&#xff09;工具-GIF中文…

【PLC】PROFIBUS(一):介绍

1、简介 PROFIBUS (Process Fieldbus)&#xff0c;德国SIEMENS和其它机构联合开发&#xff1b; 1999年&#xff0c;PROFIBUS成为国际工业现场总线协议标准IEC61158的组成部分&#xff1b; PROFIBUS 由三部分组成&#xff1a;PROFIBUS-DP、PROFIBUS-PA 和 PROFIBUS-FMS&#xf…

038—pandas 重采样线性插补

前言 在数据处理时&#xff0c;由于采集数据量有限&#xff0c;或者采集数据粒度过小&#xff0c;经常需要对数据重采样。在本例中&#xff0c;我们将实现一个类型超分辨率的操作。 思路&#xff1a; 首先将原始数据长度扩展为 3 倍&#xff0c;可以使用 loc[] 方法对索引扩…

Power Query 中转换时区

当我们的数据库在国内&#xff0c;使用报表的是国外的人时&#xff0c;通常数据库的刷新时间都会设置为UTC&#xff0c;这时我们就学院根据不同国家的时区来设置相对应的时间。我们就要用到时区的转换。 具体的步骤如下&#xff1a; 1&#xff0c;把时间转换为UTC的时区 添加…

眼观百遍,不如手敲一遍

眼观百遍&#xff0c;不如手敲一遍 Repetitive Viewing Cannot Surpass Hands-on Typing 在现代教育体系中&#xff0c;编程已成为一项基础而关键的技能。伴随着各种便捷的工具和在线资源的普及&#xff0c;获取并复制代码变得前所未有地容易。然而&#xff0c;在这种趋势下&am…
最新文章