[C++]:1.初识C++和C语言缺陷补充。

初识C++和C语言缺陷补充

  • 一.主要内容:
  • 二.具体内容:
    • 一: 作用域
      • 1.命名空间:
      • 2.函数声明和定义:
      • 3.不存在命名冲突的情况:
    • 二.输入输出:
      • 1.基本输入输出:
      • 2.关于std的展开:
    • 三.函数:
      • 1.缺省参数(部分):
      • 2.全缺省:
      • 3.缺省参数的定义和参数的传递
      • 4.函数重载:
        • >1.参数个数:
        • >2.类型:
        • >3.类型顺序:
        • >4.总结:如果存在一种情况:
      • 5.为什么出现函数重载?(编译链接的原理):
        • 1.预编译(预处理)
        • 2.编译
        • 3.汇编
        • 4.链接:
      • 6.引用:
      • 1.基本概念:
        • 1-1:关于函数的引用:
        • 1-2:引用用的特殊:
        • 1-3:常引用:
      • 2.常规用法:
        • 1.作为函数参数:
        • 2.作为函数返回值:
      • 3.特殊用法:
        • 1.解决方法一:二级指针:
        • 2.解决方法二:引用:
      • 4.总结:
      • 7.内联函数:
        • 1.概念:
        • 2.inline的优缺点:

一.主要内容:

1.对于C++ 来说是在C语言的基础之上刚开始进行对C语言的缺陷进行了优化解决,加入面向对象的编程思想,加入了非常多有用的库,和一些编程范式。对于C语言比较属性那么对于C++的学习是有帮助的。
2.那么C++对于C语言的一些些缺陷是在那一些方面呢?包括有作用域,IO方面,函数方面,指针,宏方面进行了修改。

二.具体内容:

一: 作用域

1.命名空间:

1.在C语言中存在这样的一个情况我们使用一个全局变量的时候有可能在命名变量名称的时候和C语言标准库中的内容产生冲突(1.我们的标准库在全局展开会和自己的变量名称冲突 2.在我们做一个项目的时候我们定义的变量名函数名和其他人会有冲突)。

请添加图片描述
请添加图片描述
请添加图片描述

2.解决方法:使用命名空间这一个C++提供的语法:namespace关键字,它可以把我们本地定义的内容进行包裹,在正常开始访问变量的时候默认只访问全局。下面这个代码没有进入命名空间在全局只有一个rand函数所以打印出来了一个随机值。

请添加图片描述

3.如何使用自己的命名空间呢?
:: 域作用限定符 命名空间名称+域作用限定符去访问这个命名空间。
命名空间中可以放什么东西呢?
变量名,函数声明,函数定义,结构体,联合体,枚举,等等。

请添加图片描述

4.如果出现了在一个命名空间中有两个这个同名称的变量或者函数等等。非常容易解决这个问题因为我们C++是支持命名空间的嵌套的:

请添加图片描述

2.函数声明和定义:

1自己的函数声明放在自己的命名空间中自己的定义放在自己的命名空间中在我们进行定义和声明分离的时候我们要把定义和声明放在同一个空间中:

#include"Stack.h"namespace sfpy_stack {//函数定义://1.初始化:void InitStack(struct Stack* st1){assert(st1 != NULL);StData* tmp = (StData*)malloc(sizeof(StData) * 4);if (tmp == NULL){perror("malloc file");exit(-1);}st1->st = tmp;st1->top = 0;st1->capacity = 4;}//2.插入数据:void StackPush(struct Stack* st1, StData x){if (st1->top == st1->capacity){StData* tmp = (StData*)realloc(st1->st,(sizeof(StData)*((st1->capacity)*2)));if (tmp == NULL){perror("malloc file");exit(-1);}st1->st = tmp;st1->capacity = (st1->capacity) * 2;}st1->st[st1->top] = x;st1->top++;}//3.数据遍历:void StackPrint(struct Stack* st1){assert(st1 != NULL);for (int i = 0; i < st1->top; i++){printf("%d ", st1->st[i]);}}//4.栈销毁void StackDestory(struct Stack* st1){free(st1->st);st1->st = NULL;}
}??????????????????????????????????????????#include<stdio.h>
#include<stdlib.h>
#include<assert.h>namespace sfpy_stack {typedef int StData;typedef struct Stack{StData* st;int top;int capacity;}sk;//函数声明://1.初始化:void InitStack(struct Stack* st1);//2.插入数据:void StackPush(struct Stack* st1, StData x);//3.数据遍历:void StackPrint(struct Stack* st1);//4.栈销毁void StackDestory(struct Stack* st1);
}#include"Stack.h"int main()
{//1.定义一个结构体:struct sfpy_stack::Stack st;//1-1:在有struct的情况下//我们定义结构体变量使用上面这个方法//sfpy_stack::struct Stack st2;//1-2:重命名之后就可以使用下面这个方法://sfpy_stack::sk st2;//2.进行初始化:sfpy_stack::InitStack(&st);//3.数据插入:sfpy_stack::StackPush(&st, 1);sfpy_stack::StackPush(&st, 2);sfpy_stack::StackPush(&st, 3);sfpy_stack::StackPush(&st, 4);sfpy_stack::StackPush(&st, 5);sfpy_stack::StackPush(&st, 6);//4.栈数据的打印:sfpy_stack::StackPrint(&st);//4.进行销毁:sfpy_stack::StackDestory(&st);return 0;
}

3.不存在命名冲突的情况:

1.如何打开命名空间:使用using namespace spfy_stack;
2.打开命名空间就可以不使用域限定操作符直接使用变量函数等。
3.在我们的个人作业不存在命名冲突的情况使用using namespace spfy_stack ,可以在你去使用命名空间内容就可以不使用域限定操作符:
请添加图片描述

二.输入输出:

1.基本输入输出:

1.C++ 官方标准库iostream。
2.我们的std空间名称是C++的官方定义的输入输出相关的命名空间。

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

2.关于std的展开:

1.std是C++ 标准库中的一个命名空间他的展开是需要考虑情况的因为对于一个由多个人完成的项目来说这个空间是不可以展开的。
2。在自己的练习上面去使用using namespace std;打开标准库的这一个命名空间,这样可以不需要去使用标准库名称和域限定操作符。
3-1:换行的多种方法:
3-1:1.在字符串中结尾使用\n. 2.在输出到控制台的单词后面加一个“\n”.3.使用endl结尾这个是std这个命名空间中的一个用来换行的根第2个是同样的效果。
endl==end line

请添加图片描述

4:如果存在一种情况需要换行多次但是其他的std中的有冲突(不允许完全打开命名空间)我们可以只打开命名空间中的一个操作符。

三.函数:

1.缺省参数(部分):

如果我们给这个函数的这个变量进行了传参我们就使用我们的传参,如果我们没有去进行传参就使用默认的缺省参数
2.作用:我们开辟栈空间知道要看多少空间和不知道需要开多少空间:
2-1:不知道要开多少空间我们就使用默认开辟空间的值后面动态增长:
2-2:知道要开多少空间我们就使用传参的值一下开辟好空间不需要多次判断扩容:
2-3:函数相同在存在一个缺省值的情况下完成了多个功能。

注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。

请添加图片描述
请添加图片描述

2.全缺省:

1.函数的参数全部都具有缺省值这样我们对于一个函数就有n+1种调用方式:为什么可以使用相同的函数名称呢?我们接下来再说!
请添加图片描述

3.缺省参数的定义和参数的传递

1`.缺省参数值只能从右往左给。
2.函数传实参只能从左往右。
3.如果我们给了全部缺省我们不能跳跃的进行实参传递。
4.函数的声明和定义中不要同时出现缺省参数我们一般在函数的声明中给缺省值,如果函数的定义和声明中都有缺省值我们的编译器不知道使用哪一个缺省值。

请添加图片描述

4.函数重载:

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

>1.参数个数:

请添加图片描述

>2.类型:

请添加图片描述
请添加图片描述

>3.类型顺序:

请添加图片描述请添加图片描述
请添加图片描述

>4.总结:如果存在一种情况:

事情A单独出现必须去做。
事情B单独出现必须去做。
事情A和B同时出现怎么办?编译器面对这样的情况不知道怎么办的那就报错:
A:妈妈掉水里了 B:爸爸掉水里了

5.为什么出现函数重载?(编译链接的原理):

为什么C++支持函数重载但是C语言不支持函数重载呢?

定义:Func.cpp
声明:Func.h
主函数:text2.cpp

//Func.cpp
int  add(double b, int c)
{return b + c;
}int add(int b, double c)
{return b + c;
}
//Func.h
#include<iostream>int  add(double b, int c);int add(int b, double c);//text2
#include"Func.h"using namespace std;int main()
{//1.参数不同:cout << add(2.2, 3) << endl;cout << add(2, 3.3) << endl;return 0;
}

这里我们通过linux进行预编译,编译,汇编,链接整个过程:

1.预编译(预处理)

1.头文件的展开,宏替换,条件编译,去掉注释
生成:通过预编译生成==func.i test2.i文件

请添加图片描述

2.编译

2.编译进行:语法分析,词法分析,语意分析,符号汇总。
生成:通过编译生成汇编代码:Func.s text2.s请添加图片描述
通过vim观察一下汇编代码我们看一看两个函数的地址名称:
关于linux下的函数定义的汇编代码通过什么方法命名的呢?
_Z + (函数名字符个数) +(函数名称)+参数类型的首字母:
通过观察下面两个函数名称我们就可以看出来!!!
请添加图片描述

通过vs上的反汇编我们可以观察到两个函数定义call的地址是不相同的!
在vs下定义相同函数名称的函数重载的方法比较linux下的是,windows下是通过特殊符号(对应一个类型)进行的函数名称的汇编定义!!
请添加图片描述

3.汇编

在linux下汇编后生成的二进制文件是是以.o结尾的文件,在linux下生成的是以.obj
为后缀的二进制文件。
请添加图片描述

4.链接:

链接机器会把各种.o文件和并对文件需要的库进行链接生成可执行的二进制文件 .out
如果我们的函数没有定义在func.cpp中那么到链接的时候会显示链接错误说明链接错误是发生在链接的过程中!!!!。这个时候我们的代码已经生成了二进制的机器码了。但是在链接的过程中找不到函数的定义了!!!

请添加图片描述

6.引用:

1.基本概念:

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

请添加图片描述
请添加图片描述

1-1:关于函数的引用:

请添加图片描述

1-2:引用用的特殊:

1.引用必须要初始化:
2.一个变量可以被多次引用:
3.一个引用只能被初始化一次之后如果a=b(a已经引用初始化过了b对a是赋值操作)

请添加图片描述

1-3:常引用:

1.常引用:常表示的是常变量。
2.给一个常量取别名:
2-1:访问打印 或者 进行改变(常量是不可以改变的)

图1
请添加图片描述

从图1到图2是一种权限的缩小,原来的引用可以干两个事情
1.通过引用改变–引用的变量的值。2。获取引用变量的值进行打印:
3.图二中的引用只能做(获取引用变量的值进行打印)

图2:
请添加图片描述

图三:
请添加图片描述

图四:
请添加图片描述

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

图6
在这里插入图片描述

图7:
请添加图片描述
图8:

请添加图片描述
请添加图片描述

总结我们观察上面的两个图片我们会发现引用和指针在汇编实现的时候是相同的但是题目有不同的作用:
1.在语法上r是ch的别名改变r就是改变ch
2.但是在底层r是开辟了一个4字节空间用来保存地址:

2.常规用法:

1.作为函数参数:

swap函数用来交换数值:
请添加图片描述

2.作为函数返回值:

在这里插入图片描述

如何保存函数返回值:
1.函数返回值比较小的时候就用一个寄存器去保存函数返回值:
2.函数返回值比较大的时候在main和函数栈帧空间中开辟一个位置保存这个返回值。
3ret的值取绝于函数栈帧销毁之后是否清理空,清理的化就是随机值不清理就是上面的情况但是范围一个不属于当前代码的空间是比较危险。

请添加图片描述

怎么样引用才可以作为函数返回值呢:
1.这个变量在函数栈帧销毁的时候它不会被销毁:
1-1:static静态变量(存放在静态区)
1-2:开辟在堆区的变量(存放在堆区)

请添加图片描述

请添加图片描述

3.特殊用法:

1.我们在模拟实现单链表的时候因为进行开始的头节点的改变和头插都需要改变头节点而传了一个二级指针的操作:

请添加图片描述

1.解决方法一:二级指针:

我们通过二级指针的方法就可以直接改变我们头节点的地址:
请添加图片描述

2.解决方法二:引用:

通过上面的知识我们知道int是可以有别名的int*有别人名的。当然结构体类型有别名的。结构体指针类型有别名。

请添加图片描述

4.总结:

1.引用在语法上就是另一个变量的别名,指针是存储了另一个变量的地址。
2.引用必须初始化,指针无所谓初始化。
3.引用初始化是一种传址,后面的赋值都是一种改变变量数值的操作。
4.引用初始化一个变量之后就不可以在引用其他变量,然鹅指针可以在任何时候指向另一个同类型的实体:
5.sizeof 中的含义不同因为我引用是你的别名应该有你的所有属性所以sizeof大小应该满足引用类型的字节大小,指针类型是地址地址在32为平台下就是4字节:
6.引用++ 就是引用的实际个体数值++,指针++就是向后移动应该类型的字节大小。
7.有多级指针但是没有多级引用。
8.访问实体的方式不同,指针靠解引用,引用靠编译器自己处理。
9.引用比指针使用起来更加安全,这个安全是相对的内容。

7.内联函数:

关于宏:
优点:
1.不需要开辟函数栈帧,节省空间。
2.宏的效率会快一些。
缺点:
1.容易出现优先级的问题。
2.不可以调试
3.宏的内容过多会产生空间的浪费。
4.宏是没有类型检查的。

1.概念:

一个inline加在一个函数的前面就让这个函数获得了宏的所有优点但是并没有宏的一些缺陷(优先级,函数调试,类型检查),内联提高了函数的运行效率:

请添加图片描述

1.因为inline是一个对代码的优化,默认不会打开这个代码优化。
请添加图片描述
请添加图片描述

打开之后的结果:
请添加图片描述

2.inline的优缺点:

1.inline是具有不错的优点但是inline不是一个非常好的处理方法。
2.inline本质上是一个用空间换时间的做法,如果编译器把函数当作内联函数处理。那么在代码进行预编译的时候我们就进行替换,好处:节省了调用函数栈帧的时间消耗,缺点:导致目标文件变大。
3.inline对于编译器只是一个建议,不同的的编译器对于inline的实现的机制可能不同,一般函数比较小,不是递归并且频繁调用的函数可以去用inline修饰。
4.inline不建议定义和声明分开会导致连接错误因为inline函数需要展开但是如果定义和声明分离展开是没有内容的(找不到函数地址链接找不到的)。

5.优点:
1.有宏的所有优点,没有宏的缺点
2.频繁调用一个小函数效率是比较高的:
6.缺点:
1.内联函数比较大,就会大大使用了目标空间。
2.使用一个较大函数我们内联就都会去编译函数代码,对于正常的函数调用只会编译一条函数代码。

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

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

相关文章

5+非肿瘤分析,分型+WGCNA+机器学习筛选相关基因

今天给同学们分享一篇非肿瘤分型机器学习WGCNA实验的生信文章“Identification of diagnostic markers related to oxidative stress and inflammatory response in diabetic kidney disease by machine learning algorithms: Evidence from human transcriptomic data and mou…

Windows网络系统架构

在介绍Windows网络体系架构之前&#xff0c;我首先介绍一下Windows中的两个重要编程规范——TDI&#xff0c;NDIS.&#xff0c;然后再介绍网络体系的架构。TDI&#xff0c;Transport Driver Interface&#xff0c;传输驱动程序接口。/Windows/System32/Drivers/Tdi.sys。在实现…

搜索引擎站群霸屏排名源码系统+关键词排名 前后端完整的搭建教程

开发搜索引擎站群霸屏排名系统是一项重要的策略&#xff0c;通过在搜索引擎中获得多个高排名站点&#xff0c;可以大大提高企业的品牌知名度&#xff0c;从而吸引更多的潜在客户和消费者。而且当潜在客户在搜索结果中看到多个与您的品牌相关的站点时&#xff0c;他们可能会认为…

Thread常用API

setname方法每个线程取名 需要创建构造器 线程设置名字 package Thread_api_test;// 继承Thread类 public class MyThread extends Thread {//创建构造器 线程设置名字public MyThread(String name){super(name);}Overridepublic void run() {super.run();Thread mThread.cur…

css 左右滚轮无缝衔接

最近的项目有做到一个功能 类似跑马灯或者公告栏那种 有文字 也有列表的 所以 写了两种 第一种公告栏文字是用的js 第二种图文类型是用的css 两种方法 记录一下 第一种 纯文字滚动 其实也是根据js去计算dom的宽度 通过js去给css赋值 <div class"div1"><div …

计网面试复习自用

五层&#xff1a; 应用层&#xff1a;应用层是最高层&#xff0c;负责为用户提供网络服务和应用程序。在应用层&#xff0c;用户应用程序与网络进行交互&#xff0c;发送和接收数据。典型的应用层协议包括HTTP&#xff08;用于网页浏览&#xff09;、SMTP&#xff08;用于电子邮…

【MySQL】事务四大特性ACID、并发事务问题、事务隔离级别

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 MySQL 一、事务四大特性ACID1.1 原子性1.2 …

车辆车型识别系统python+TensorFlow+Django网页界面+算法模型

一、介绍 车辆车型识别系统。本系统使用Python作为主要开发编程语言&#xff0c;通过TensorFlow搭建算法模型网络对收集到的多种车辆车型图片数据集进行训练&#xff0c;最后得到一个识别精度较高的模型文件。并基于该模型搭建Django框架的WEB网页端可视化操作界面。实现用户上…

【LeetCode刷题(数据结构与算法)】:二叉树之左叶子之和

给定二叉树的根节点 root &#xff0c;返回所有左叶子之和 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 24 示例 2: 输入: root [1] 输出: 0 这都题目用递归的方法就可以解决…

『C++之STL』双端队列 - deque

前言 双端队列,Double-ended queue,简称为deque是一种线性结构的一种容器; 在数据结构中出现的顺序表与链表,或者栈与队列都算是线性结构; 在结构中,它与vector相比较会相似一些; 但是在实际当中,双端队列 - deque 包含了vector与list的优点; vector(顺序表) 支持随机访问,空…

Vue3引入腾讯地图,点击坐标后实时获取经纬度

本文将介绍如何在Vue 引入腾讯地图组件&#xff0c;引入后可以直接在页面中渲染腾讯地图&#xff0c;实现 经纬度 与 地图锚点位置的双向绑定&#xff0c;如&#xff1a; 1&#xff0c;输入经纬度后&#xff0c;地图自动定位到指定位置&#xff1b;2&#xff0c;鼠标在地图点击…

多域名SSL数字证书是什么呢

多域名SSL数字证书是众多SSL数字证书中最灵活的一款SSL证书产品。一般一张SSL证书只能保护一个域名&#xff0c;即使能保护多个域名站点&#xff0c;证书保护的域名类型也有限制(通配符SSL数字证书)。多域名SSL数字证书既能用一张SSL证书保护多个域名网站&#xff0c;又不限制域…

HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Toggle

组件提供勾选框样式、状态按钮样式及开关样式。该组件从API Version 8开始支持。 仅当ToggleType为Button时可包含子组件。 一、接口 Toggle(options: { type: ToggleType, isOn?: boolean }) 从API version 9开始&#xff0c;该接口支持在ArkTS卡片中使用。 参数: Toggle…

基于Java的驾校教练预约管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

AD20绘制电路板的外形

今天学习了绘制电路板外形的方法&#xff0c;记录一下&#xff0c;回头忘了还能在看看&#xff0c;便能很快的回忆起来了&#xff0c;比看视频啥的要高效的多。毕竟是自己写的&#xff0c;印象要深刻的多。 首先新建一个PCBDoc文件&#xff0c;方法如下图&#xff1a; 在新建的…

Linux服务器快速搭建pytorch

Linux服务器搭建pytorch 文章目录 Linux服务器搭建pytorch一、使用FileZilla传输Anaconda二、激活Anaconda环境1.创建一个虚拟环境2.使用已有项目生成requirements.txt3.在虚拟环境中使用requirements.txt安装其他项目相关库 总结 一、使用FileZilla传输Anaconda 提示&#xf…

倍福TwinCAT3.0软件与C++通讯问题(EAP通讯)

文章目录 一. TwinCAT控制器之间的几种通讯方式1.添加EAP设备2.添加变量刷新的Task周期3. 测试 一. TwinCAT控制器之间的几种通讯方式 协议硬件要求实时性说明ADS通讯普通网卡&#xff0c;支持无线典型值&#xff1a;< 100msServer/Client&#xff0c;要写 PLC 程序&#x…

onlyoffice的介绍搭建、集成过程。Windows、Linux

文章目录 什么是onlyoffice功能系统要求安装必备组件 windows搭建资源下载安装数据库onlyoffice安装测试 Linux搭建dockerdocker-compose 项目中用到的技术&#xff0c;做个笔记哈~ 什么是onlyoffice 在本地服务器上安装ONLYOFFICE Docs Community Edition Community Edition…

网络安全—小白学习笔记

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟入…

AC修炼计划(AtCoder Regular Contest 165)

传送门&#xff1a;AtCoder Regular Contest 165 - AtCoder 本次习题参考了樱雪猫大佬的题解&#xff0c;大佬的题解传送门如下&#xff1a;Atcoder Regular Contest 165 - 樱雪喵 - 博客园 (cnblogs.com) A - Sum equals LCM 第一题不算特别难 B - Sliding Window Sort 2 对…