C++入门

目录

一:关键字

二:命名空间

1.引入

2.命名空间的定义               

<1>:命名空间中定义变量/函数/类型 

<2>:命名空间可以嵌套

<3>:同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中

3.命名空间的使用

<1>:加命名空间名称及作用域限定符

 <2>:使用using namespace 命名空间名称引入

 <3>:使用using将命名空间中某个成员引入

三:输入、输出

四:缺省参数

1.缺省参数的概念

2.缺省参数的分类 

<1>:全缺省参数

<2>:半缺省参数

 <3>:注意

五:函数重载 

1.函数重载概念

2.C++支持函数重载的原理 --- 名字修饰

<1>:C语言不支持函数重载的原因

<2>:两者编译后对比 

 六:引用

1.引用的概念

2.引用的特性

3.引用作返回值

<1>:传值返回

 <2>:传引用返回

 4.引用做参数

<1>引用做参数 

 <2>:引用做参数和做返回值的对比

5.常引用

6.引用和指针的区别

七:内联函数

1.内联函数概念

 2.特性

 八:auto 关键字

九:范围for

十:指针空值


一:关键字

C++总计63个关键字,C语言32个关键字

二:命名空间

1.引入

在打印 rand 的值时,无法得到我们想要的结果。

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存 在于全局作用域中,可能会导致很多冲突。
使用命名空间的目的是对标识符的名称进行本地化,避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

2.命名空间的定义               

 定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{} 中即为命名空间的成员。

<1>:命名空间中定义变量/函数/类型 

#include <iostream>
namespace rsg
{// 命名空间中可以定义变量/函数/类型int rand = 10;//定义变量int Add(int left, int right)//定义函数{return left + right;}struct Node//定义结构体类型{struct Node* next;int val;};
}

<2>:命名空间可以嵌套

#include <iostream>
namespace rsg
{int a;int b;int Add(int left, int right){return left + right;}namespace zrsg{int c;int d;int Sub(int left, int right){return left - right;}}
}

 程序可以正常退出,上述代码没有问题。命名空间可以嵌套。 

<3>:同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中

#include <iostream>
namespace rsg
{// 命名空间中可以定义变量/函数/类型int rand = 10;//定义变量int Add(int x, int y)//定义函数{return x + y;}
}
namespace rsg
{int a = 3;int b = 4;int c = 5;
}

 两个 rsg 的命名空间最后会合并在一起。

3.命名空间的使用

观察下述代码,猜测程序运行的结果???

#include <iostream>
namespace rsg
{int a = 10;//命名空间定义变量int Add(int x, int y)//命名空间定义函数{return x + y;}
}
int main()
{printf("%d\n", a);return 0;
}

通过调试运行代码,我们得到下述结果: 

 我们发现,a 为未定义的标识符 ---> 命名空间的内容是如何使用的呢 ???

<1>:加命名空间名称及作用域限定符

: : 域作用限定符

我们可以采用“命名空间 : : 命名空间成员”的方式访问命名空间内的相应的成员。 

 <2>:使用using namespace 命名空间名称引入

该方法在某些情况下会出现问题,如我们在命名空间内定义了一个 printf 变量,当我们使用该命名空间时,会造成 printf 为不明确符号:

 为此,添加了一种新的方法。

 <3>:使用using将命名空间中某个成员引入

a --- 未定义的标识符,b 是正常的 :

三:输入、输出

#include <iostream>
//std 是C++标准库的命名空间
using namespace std;
int main()
{cout << "Hello World" << endl;return 0;
}

程序运行结果为:

std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?
1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对
象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模
大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 +
using std::cout展开常用的库对象/类型等方式。
 
cout --- 控制台输出(控制台)
<< --- 流插入运算符
>> --- 流提取运算符
endl --- 换行符,等价于 ' \n ' (此处为字母l,不是数字1)
cin --- 标准输入对象(键盘)
 
使用cout标准输出对象(控制台)cin标准输入对象(键盘)时,必须包含< iostream >头文件
以及按命名空间使用方法使用std。

四:缺省参数

1.缺省参数的概念

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

2.缺省参数的分类 

<1>:全缺省参数

#include <iostream>
//std 是C++标准库的命名空间
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;
}

程序运行结果为:

<2>:半缺省参数

注:下属图片中,半缺省为从右向左给缺省值 

部分图片有误。

#include <iostream>
//std 是C++标准库的命名空间
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);//Func();return 0;
}

至少传一个参数:

程序运行结果为:

 <3>:注意

1. 半缺省参数必须从右往左依次来给出,不能间隔着给

2. 缺省参数不能在函数声明和定义中同时出现
当声明和定义同时出现时(缺省参数):

 在声明中给,在定义中就不需要再给了,正确情况下为:

3. 缺省值必须是常量或者全局变量
4. C语言不支持(编译器不支持)

五:函数重载 

1.函数重载概念

函数重载(一个词有多重含义):是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
 
<1>:C语言不允许同名函数(重定义)
<2>:cpp可以,但是要求构成函数重载
  
类型不同:

<3>:函数名相同,参数不同(类型不同、个数不同、顺序不同)
在 <2> 中我们已经使用了参数类型不同,接下来举例后面两种情况
个数不同:

   

顺序不同:

2.C++支持函数重载的原理 --- 名字修饰

<1>:C语言不支持函数重载的原因

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接
示例:
Test.cpp
// 预处理 :<1>:头文件的展开 <2>:宏替换 <3>:去掉注释 <4>:条件编译
Test.i
// 编译 (检查语法)生成汇编代码(指令级代码 eg:push、sub....)
<1>:语法分析 <2>:词法分析 <3>:语义分析 <4>:符号分析
Test.s
// 汇编 --- 将汇编代码转换成二进制指令(机器码) 形成符号表 同名函数出错
Test.o
// 链接 合并链接,生成可执行程序 符号表的合并和重定位
Test.exe 二进制的指令(机器指令)

<2>:两者编译后对比 


通过下面我们可以看出gcc的函数修饰后名字不变。
而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】

测试用例:


 C语言编译器编译结果(linux 平台下):

C++编译器编译结果(linux 平台下): 

 

 六:引用

1.引用的概念

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

 如上,b 为 a 的引用,即为 a 的别名( a , b 为同一块内容),所以取地址a 和 取地址b 的地址值相同。对b进行++,a 也会变。

使用示例:

 x 为 a 的引用, y 为 b 的引用,改变 x,y的值,a,b的值会被被改变。

2.引用的特性

<1>:引用在定义时必须初始化

<2>:一个变量可以有多个引用

<3>:引用一旦引用了一个实体,再不能引用其他实体

3.引用作返回值

<1>:传值返回

n 出函数栈帧 --- 销毁 != 空间没了

返回值 n ,通过一个临时变量(可为寄存器)传给ret 。 

 <2>:传引用返回

函数调用,先传参,后建立栈帧。

传引用返回时,可能会出现栈帧覆盖情况。

空间被清 --- 随机值

空间不被请 --- 1(下图示例)

 返回的值是 a 的别名(引用)

通过下述的示例,让我们更好的理解空间覆盖。 


观察下述代码,分析结果???

#include <iostream>
using namespace std;
int& Add(int x, int y)
{int z = x + y;return z;
}
int main()
{int& ret = Add(3, 4);Add(5, 5);cout << "Add(3,4) is " << ret << endl;return 0;
}

显而易见 3 + 4 = 7,让我们看一下程序运行的结果:

 我们发现程序的最终的结果与我们预想的不一样???

z 为返回的对象,但出了Add的函数栈帧,z 就会被销毁(空间仍然存在),在下一次函数调用时,会将该空间覆盖掉(栈帧),返回一个新的 z 的值。此情况非常不安全。

如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用
引用返回,如果已经还给系统了,则必须使用传值返回。

 4.引用做参数

<1>引用做参数 

 <2>:引用做参数和做返回值的对比


传引用传参(任何时候都可以使用)

*1   提高效率

*2   输出型参数(形参的修改,影响实参)

传引用返回(出了函数作用域对象还在才可以使用)

*1  提高效率

*2  修改返回对象


5.常引用

观察下面三个示例: 

被 const 修饰的值在引用过程中不能给不被 const 修饰的值,该情况属于权限的放大。

 const 修饰的值在引用过程中给被 const 修饰的值,该情况属于权限的平移。

 不被 const 修饰的值在引用过程中给被 const 修饰的值,该情况属于权限的缩小。

在引用过程中:

权限可以平移,可以缩小,但不能放大。

查看下述代码:

 从反汇编我们可以看出, i 赋值给一个临时变量,然后赋值给a 

临时变量具有常性。

在此处,并非为权限的平移,参数类型不同。

解决方法,在double 前面加上 const : 

6.引用和指针的区别

 观察 引用和指针的反汇编:

 我们发现两者反汇编语言相同,由此得出结论:

底层只有指针,没有引用(汇编一层,没有引用的概念)


引用和指针的不同点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求。
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体。
4. 没有NULL引用,但有NULL指针。
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
位平台下占4个字节)。
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。
7. 有多级指针,但是没有多级引用。
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理。
9. 引用比指针使用起来相对更安全。 

七:内联函数

1.内联函数概念

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。

 原来的非内联函数:

      如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的调用。

 上述结果的查看方式:

 

 2.特性

1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会
用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运
行效率。
2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建
议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不
是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。
3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址
了,链接就会找不到。

假如Func是一个100行的一个函数。我们在100个位置进行函数调用 :

是内联(inline)合计多少行指令??? // 1000 行

不是内联(inline)合计多少行指令??? // 200 行 --- call Func 每个地方100行函数调用+Func(100行的一个函数)。


test.h文件 

#pragma once#include <iostream>
using namespace std;void Func(int i);//1
//void F();//2
//inline void Func(int i);//3

在情况1 --- 正常

 在只有情况3 --- 报错,无法解析的外部符号,连接错误。

只包含了 test.h ,只有声明。

 情况1和2 --- 可以正常运行,F函数既有声明,又有定义。

 情况2和3 --- 可以正常运行 -> F函数存在(F函数调到了Func函数???在只有情况3的时候,我们没有掉到Func函数)

原因:2和3情况下,F函数中的Func(1),既有函数(Func)的声明,又有定义,在此处并没有函数调用,而是在此处直接展开,它不需要地址。

 解决上述问题问题的方法为:声明+内联 且不可分离

#pragma once#include <iostream>
using namespace std;inline void Func(int i)
{cout << "inline void Func(int i)" << i << endl;
}

 八:auto 关键字

示例:

 查看 c 的类型,为 int* 指针类型。

注意:

<1>: auto 不能作为函数的参数

 

<2>: auto 不能直接用来声明数组

九:范围for

打印一个数组乘2后的数组: 

 橙色方框与黄色方框的最终结果相同。黄色方框使用了范围 for 

范围 for :

<1>: 依次读取数组中的数据赋值给e 

<2>: 自定判断结束

<3>: 自动迭代(++、--)


 在此处如果使用 for (auto &x : arr) 会产生怎样的结果???

 由上述可知,传入的 arr 的值为第一次乘2后的结果,修改 x , arr 的值被改变。


for (auto x : arr) 

 修改 x , arr 的值不受影响。


十:指针空值

NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量 

 不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦。

在此处,我们可以使用 nullptr 来取代 NULL 。

注意:
1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

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

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

相关文章

【设计模式】建造者模式

建造者模式&#xff08;Builder Pattern&#xff09;使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。 介绍 …

idea入门与maven配置的一些介绍

idea入门与maven配置的一些介绍 1.确保Java和Maven已安装2.创建一个新的Maven项目3.导航到要创建项目的目录配置Maven4.配置项目的pom.xml文件5.配置其他Tomcat和设置jdk6.构建和运行项目 关于idea入门基础配置 步骤1&#xff1a;安装IntelliJ IDEA 首先&#xff0c;从IntelliJ…

【Vue-Router】命名视图

命名视图 同时 (同级) 展示多个视图&#xff0c;而不是嵌套展示&#xff0c;例如创建一个布局&#xff0c;有 sidebar (侧导航) 和 main (主内容) 两个视图&#xff0c;这个时候命名视图就派上用场了。 可以在界面中拥有多个单独命名的视图&#xff0c;而不是只有一个单独的出…

JVM内存区域划分

JVM把虚拟机的内存区域划分为方法区&#xff08;Method Area&#xff09;、堆&#xff08;Heap&#xff09;、栈&#xff08;Java Stack&#xff09;、本地方法栈&#xff08;Native Method Stack&#xff09;、和一个PC寄存器&#xff08;程序计数器&#xff0c;Progam Counti…

msvcp140.dll如何重新安装?快速安装msvcp140.dll的方法分享

msvcp140.dll是Windows操作系统的一个动态链接库文件&#xff0c;它是Microsoft Visual C Redistributable的一部分。这个文件在运行某些应用程序时非常重要。然而&#xff0c;在某些情况下&#xff0c;msvcp140.dll文件可能会损坏或遗失&#xff0c;导致应用程序无法正常运行。…

神经网络基础-神经网络补充概念-03-逻辑回归损失函数

概念 逻辑回归使用的损失函数通常是"对数损失"&#xff08;也称为"交叉熵损失"&#xff09;或"逻辑损失"。这些损失函数在训练过程中用于衡量模型预测与实际标签之间的差异&#xff0c;从而帮助模型逐步调整权重参数&#xff0c;以更好地拟合数…

堆的实现以及应用

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大家三连关注&…

Unity zSpace 开发

文章目录 1.下载 zSpace 开发环境1.1 zCore Unity Package1.2 zView Unity Package 2. 导入工程3. 发布设置4.功能实现4.1 用触控笔来实现对模型的拖拽&#xff1a; 5. 后续更新 1.下载 zSpace 开发环境 官网地址 1.1 zCore Unity Package zSpace 开发核心必须 1.2 zView …

K8S系列三:单服务部署

写在前面 本文是K8S系列第三篇&#xff0c;主要面向对K8S新手同学&#xff0c;阅读本文需要读者对K8S的基本概念&#xff0c;比如Pod、Deployment、Service、Namespace等基础概念有所了解。尚且不熟悉的同学推荐先阅读本系列的第一篇文章《K8S系列一&#xff1a;概念入门》[1]…

图解 Paxos 算法

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱写博客的嗯哼&#xff0c;爱好Java的小菜鸟 &#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&#x1f44d;一下博主哦 &#x1f4dd;个人博客&#xff1a;敬请期待 &#x1f4d5;系列…

ROS学习笔记(二)---使用 VScode 开发 ROS 的Python程序(简例)

一、任务介绍 本篇作为ROS学习的第二篇&#xff0c;是关于如何在Ubuntu18.04中使用VSCode编写一个Python程序&#xff0c;输出“Hello&#xff01;”的内容介绍。 首先我们来了解下ROS的文件系统&#xff0c;ROS文件系统级指的是在硬盘上ROS源代码的组织形式&#xff0c;其结构…

东方晶源亮相第十一届半导体设备年会,共话发展“芯”机遇

8月11日&#xff0c;以“协力同芯抢机遇&#xff0c;集成创新造设备”为主题的第十一届&#xff08;2023年&#xff09;中国电子专用设备工业协会半导体设备年会暨产业链合作论坛&#xff08;CSEAC&#xff09;在无锡太湖国际博览中心圆满闭幕。为期3天的CSEAC&#xff0c;通过…

安装Linux操作系统CentOS 6详细图文步骤

为满足业务对Linux操作系统部署的要求&#xff0c;本文档主要提供CentOS 6操作系统的最小化安装和基本配置, 安装本系统建议最少1GB内存和2GB磁盘空间。 1、 使用光盘或者挂载ISO镜像&#xff0c;在出现如下图形界面时选择【Install or upgrade an existing system】并按Ent…

Redis 缓存过期及删除

一、Redis缓存过期策略 物理内存达到上限后&#xff0c;像磁盘空间申请虚拟内存(硬盘与内存的swap),甚至崩溃。 内存与硬盘交换 (swap) 虚拟内存&#xff0c;频繁I0 性能急剧下降&#xff0c;会造成redis内存急剧下降&#xff1b; 一般设置物理内存的3/4&#xff0c;在redis…

【C/C++】STL queue 非线程安全接口,危险!

STL 中的 queue 是非线程安全的&#xff0c;一个组合操作&#xff1a;front(); pop() 先读取队首元素然后删除队首元素&#xff0c;若是有多个线程执行这个组合操作的话&#xff0c;可能会发生执行序列交替执行&#xff0c;导致一些意想不到的行为。因此需要重新设计线程安全的…

每天一道leetcode:剑指 Offer 13. 机器人的运动范围(中等广度优先遍历剪枝)

今日份题目&#xff1a; 地上有一个m行n列的方格&#xff0c;从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0]的格子开始移动&#xff0c;它每次可以向左、右、上、下移动一格&#xff08;不能移动到方格外&#xff09;&#xff0c;也不能进入行坐标和列坐标的数位之…

jmeter返回值中的中文显示为????问号处理解决方案

jmeter返回值中的中文显示为????问号 查找解决方案时&#xff0c;发现了以下两种解决方案&#xff1a; 一、1.打开jmter配置文件bin/jmeter.properties 2.修改配置文件&#xff0c;查找“sampleresult.default.encoding”将其改为utf8&#xff0c;注意要去掉“#”号 sample…

opencv带GStreamer之Windows编译

目录 1、下载GStreamer和安装2. GSTReamer CMake配置3. 验证是否配置成功 1、下载GStreamer和安装 下载地址如下&#xff1a; gstreamer-1.0-msvc-x86_64-1.18.2.msi gstreamer-1.0-devel-msvc-x86_64-1.18.2.msi 安装目录无要求&#xff0c;主要是安装完设置环境变量 xxx\1…

CVPR 2023 | 用户可控的条件图像到视频生成方法(基于Diffusion)

注1:本文系“计算机视觉/三维重建论文速递”系列之一&#xff0c;致力于简洁清晰完整地介绍、解读计算机视觉&#xff0c;特别是三维重建领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, NeurIPS, ICLR, ICML, TPAMI, IJCV 等)。 本次介绍的论…

S7-200 Smart 的多种端口及通讯方式

每个S7-200 SMART CPU都提供一个以太网端口和一个RS485端口(端口0)&#xff0c;标准型CPU额外支持SB CM01信号板(端口1)&#xff0c;信号板可通过STEP 7-Micro/WIN SMART软件组态为RS232通信端口或RS485通信端口。 CPU 通信端口引脚分配 1.S7-200 SMART CPU 集成的 RS485 通信…