C++的一些基础语法

前言:

本篇将结束c++的一些基础的语法,方便在以后的博客中出现,后续的一些语法将在涉及到其它的内容需要用到的时候具体展开介绍;其次,我们需要知道c++是建立在c的基础上的,所以c的大部分语法都能用在c++上。

目录

1.域作用限定符

2.关键字namespace

3.流插入和流提取

4.缺省(默认)参数与缺省值

a.全缺省参数

b.半缺省参数

c.注意

5.函数重载

6.指针和引用

a.语法

b.应用

c.常引用

d.指针和引用的区别

7.内联函数inline

a.复习宏

b.使用

c.内联函数的性质

8.关键字auto

a.语法

b.缺点

c.特性

d.typedef的缺点(附加)

9.范围for(c++11)

10.关键字nullptr

总结:

只介绍了c++中一些常见的基础语法,精进需要结合后面的内容,毕竟只学习语法却不了解应用是学不好的,本文如有错误请指正并会及时回复。


1.域作用限定符

首先,认识一下域作用限定符:

#include <iostream>int main()
{
std::cout<<"hello world"<<std::endl;
return 0;}

代码中域作用限定符就是::,当我们遇到在用一个项目组中使用了相同的命名的时候,除了改该怎么办?我们可以指定对应的域中去找相应的重复命名的内容,例如去某个结构体或者类中去找(类在后面会介绍);其次记住一点,如果域作用限定符的左侧为空,就是去全局里面去找。

2.关键字namespace

#include <iostream>
using namespace std;
int main()
{cout<<"hello world"<<endl;return 0;
}

首先可以明显的看到,函数里面的内容少了点什么,这就是因为我们加上了一句using namespace std;,为什么呢?

这里就开始介绍初学c++为什么要这样写程序了,因为大部分人学会使用了c++却连开始为什么要这样写都说不上一二,就有些尴尬了,首先介绍开始的头文件:

我们查阅文档可知(来源:https://legacy.cplusplus.com/reference/)iostream中包含了cin和cout等(其实它们都是iostream的对象),所以我们要想使用cout和cin等就要包含这个头文件。

那cout和cin等又是什么?我们目前记住它们是用来显示屏幕的信息和提取屏幕的信息的,分别需要搭配流插入<<和流提取>>,所以它们就都相当于c中的printf和scanf,但是不同的是它们不是库函数,而是某个类的对象,后面再提,以及与printf,scanf的区别也在后面再提。

然后endl只需要知道它是换行的意思即可。

然后就是我们的命名空间这一行,这一行是什么意思呢?首先我们需要知道

  • 用法:namespace name

{}

  • 命名空间---命名空间域,只影响使用,不影响生命周期,在多个文件使用相同的命名空间会被认为是同一个

然后我们需要知道std是c++标准库的名字,也就是说如果我们想用封装在c++标准库中的内容就需要展开这个命名空间,也就是展开标准库所在的域,这样才能使用库中的内容,如果不这样使用,cout等就会不被编译器所认识。

但是需要注意,你会在一些人的代码中发现是这样写的:

std::cout<<"hello world"<<std::endl

为什么呢?首先我们知道了命名空间的存在其实就是为了封装起你写的内容,避免其他的重复命名出现导致出问题,而如果要让标准库中的域展开,那就破坏了这道防线,因为其实封装的目的就是防止你的命名与标准库中的冲突,再使用与标准库中同名的就不行了,所以就有了这样的写法(平时练习可以直接展开,但比较大的项目中不建议这样用)。

如果我们将上方的写法称为全部展开,那下面的写法就为部分展开:

using std::cout;
using std::endl;

也就是让比较常用的展开,避免一个一个写。

3.流插入和流提取

刚刚我们已经提到了它们,例如cout<<endl就是让换行符流到控制台上,再看一个流提取的例子:

int n=0;
double* a=(double*)malloc(sizeof(double));
if(a==NULL)
{perror("malloc fail");exit(-1);
}
for(int i=0;i<n;++i)
{cin>>a[i];
}
for(int i=0;i<n;++i)
{cout<<a[i]<<endl;
}

 这是一个输入数组元素,然后打印出来的例子,从中我们可以看到cout和cin的用法,但是我们也可以发现我们在使用cout和cin的时候好像不用管a是一个double类型的数组唉?

这就是流的特性:

  • 流会自动识别类型,不需要%d%f等输入输出

至于为什么,我们将在流的内容与运算符重载中在提。

4.缺省(默认)参数与缺省值

我们知道,在c语言中,函数的参数是不能赋值的,也就是说你传来的什么就是什么,而c++有创造了一个新的玩法:

	void func(int a=0){cout<<a<<endl;}int main(){func(1);//传参就是打印传的值,也就是1func();//不传就是打印默认值0return 0;}

至于有什么用,我们在以后再说(减少重载函数的数量,简化函数的调用过程)。

a.全缺省参数

全缺省就是所以参数都缺省:

void Func(int a = 10, int b = 20, int c = 30)
{cout << "a=" << a << endl;cout << "a=" << b << endl;cout << "a=" << c << endl;cout << endl;
}int main()
{Func(1, 2, 3);return 0;
}

需要注意的是,只能从右往左缺省,且要连续,为什么呢?

因为如果你要写成:

void Func(int a = 10, int b = 20, int c )

那你传两个参数的时候,c对应的位置必须要有一个传过来的参数(因为没缺省嘛),那第一个实参是对应的a还是b,不仅编译器会报错,意义也不明;参数从右往左缺省就不会出现这样的问题。

然后就是使用缺省值要从右往左(因为参数是从右往左缺省的)连续使用,像这样不连续的就不行:

Func(,1,2);

b.半缺省参数

也就是参数可以不完全缺省,规则也和全缺省一样(从右往左连续缺省),不同的是不能不传参数,如果传一个参数就是对应最左边的参数
 

c.注意
  • 不能在声明和定义中同时给缺省参数,要在声明中给(如果声明和定义的缺省值不同,编译器无法确定,放在声明中也减少了其他源文件重复定义;还有些人说是为了保护代码的安全,因为别人copy了源码却不知道缺省值)
  • 缺省值必须是常量或者是全局变量,c语言不支持缺省参数

5.函数重载

在c中,我们知道使用函数名相同的函数是行不通的,所以本贾尼博士又发明了一个新的语法,允许函数名可以相同,但是参数的个数或者返回类型或者类型的顺序要不同的同名函数存在。

void Add(int a,int b);
void Add(int a,int b,int c);void Add(int a,int b);
void Add(double a,double b);void Add(int a,int b);
void Add(int b,int a);

那具体是怎么实现相同的函数名能找到对应的函数呢?

c++对函数名进行了修饰(此为linux的修饰规则,不同平台的修饰规则不同),例如void Add(int a,int b),会修饰成_Z3Addii,void Add(double a,double b)会修饰成_Z3Adddd,其中_Z是固定的,3是函数名长度,再加上函数名,再加上形参的类型缩写,通过不同的函数名修饰加上编译时产生的地址,就能区别出调用哪个了(浮点数默认为double)

 另外还需要注意:

  • 返回值不同的,其他都相同,不构成重载,因为编译器识别不出来,不是因为修饰名没有返回值而识别不出,而是调用函数的时候没写返回值(call这个函数的地址的时候没有返回值),区分不出来
  • 编译时就已经确定了调用那个函数 ,编译速度可能变慢,但是运行速度不会变慢

6.指针和引用

a.语法

可以看到k是i的引用,并且地址是一样的,所以我们又说k是i的别名。

同时我们还可以看到,直接赋值地址是不一样的,因为是又开辟了新的栈帧。

引用在后面的应用有很大的作用。

注意:

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

b.应用
  • 应用1(输出型参数)---实参影响形参的情况,例如改变实参的值就要传实参的地址,从而形参要用指针
	void Swap(int& x,int& y)//形参是实参的别名,地址一样,不用取地址{int tmp=x;x=y;y=tmp}
  • 应用2(做返回值)

首先,先引入传值返回:

我们可以看到:

返回的n先存到(拷贝给)一个临时变量(可能是寄存器也可能是上一层栈帧),然后count栈帧销毁,这个临时变量再给给ret,如果n是个静态的变量放在静态区,也是先存到临时变量,也不会直接返回n,此为传值返回(用于变量出了作用域就不在的情况)

如果使用传引用返回:

返回n的别名,减少了拷贝,因为n已经是静态的了,但返回时还要拷贝到一个临时变量,返回n的别名就减少了拷贝(可以理解产生了一个临时变量,但这个临时变量是n的别名,也就是n,就减少了拷贝 ),只要出了count作用域这个变量还在,就可以用传引用返回

所以使用传引用返回,我们可以得到以下结论:

  • 减少拷贝
  • 调用者可以直接修改返回的对象

我们再来看一个错误的例子:

int& Add(int a,int b)
{int c=a+b;return c; 
}int main()
{int ret=Add(1,2);//正确的int& ret=Add(1,2);//错误的
}

返回c的别名,ret又是c这块空间的别名,但是c这块空间销毁了,访问ret也是找到销毁的空间,如果c的空间被覆盖就是随机值,没有就还是那块空间

总结:

如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回(性能上有一定的提升),如果已经还给系统了,则必须使用传值返回,以此理解全局变量二者都可以(因为全局变量也是存在静态区的,所以也是先拷贝给临时变量)。

c.常引用

	const int c=2;const int& d=c;const int* p1=NULL;const int* p2=p1;const int m=1;int n=m;int count{int n=1;return n;}const int& ret=count();int i=0;const double& rd=i;

从前两个例子我们可以知道d是c的别名,c是不可改的,那d也应该是不可改的;同理指针也是(*p不能修改,但是p可以修改,需要根据const的位置,在c专栏中有介绍到这一点),

赋值或初始化,权限可以缩小(只有别名是const修饰),但是不能放大。

而第三个例子就仅仅赋值,所以n的改变不会影响到m。

第四个例子是count的返回值是n先拷贝给临时变量,再给ret,返回的这个临时变量(在此过程中)也不可改变,它的别名也要用const修饰。

第五个例子是隐式类型转换,类型转换会产生临时变量,i先给给double类型的临时变量,临时变量再给给rd,所以rd是这个临时变量的别名,而这个临时变量(因为在这个过程里面这个临时变量肯定不变嘛)具有常性,所以要加const。

d.指针和引用的区别

首先我们需要知道:

  • 从语法的角度,引用不开空间,指针需要开空间;而从底层的角度,从汇编来看二者过程一模一样,引用也是需要开空间的

其次不同点:

这里的安全是从引用没有空引用个定义必须初始化出发的,因为有时指针的一些错误不会直接报错。

7.内联函数inline

a.复习宏

c++推荐使用enum和const代替宏常量,inline代替宏函数。

我们来复习一下宏的优缺点:

优点:

  • 类型可以不固定
  • 不用建立栈帧

缺点:

  • 不能调试

  • 没有类型安全的检查

  • 有些场景非常复杂(例如add宏函数)

#define ADD(x,y)((x)+(y))

1.为什么x+y要加括号,因为宏只是替换,例如ADD(1,2)*3;不加括号就达不到效果了

2.为什么里面的x和y分别要加括号?因为例如ADD(a|b,a&b);宏会替换成a|b+a&b,而加号  

   优先级更高,也达不到想要的效果

3.加分号也不行ADD(1,2)*3;宏会替换成((1)+(2));*3;会报错

b.使用
	inline int Add(int x,int y){int z=x+y;return z;}

用汇编查看可知在调用内联函数时就展开了函数的逻辑,不用建立栈帧:

如果存在call Add就是没有展开函数,也就不是内联;红色箭头指向的就是没有call 这个函数的地址,直接展开函数体,使用了内联。 

c.内联函数的性质

关于第三点:
假设在头文件中声明一个内联函数,再在函数实现文件中定义一个内联函数,此时在主函数中使用内联函数就会链接报错,因为虽然主函数引用了头文件,但是内联函数是直接展开的,没有地址,头文件只定义了内联函数,但找不到内联函数的地址(也就是出现在了声明中,但是展开时找不到函数体),所以建议定义和声明都在头文件里。

注意:

如果成员函数在类中定义,编译器可能会将它当做内联函数处理。

所以在stl源码里面有些短小的函数直接就放在类里面定义了,就是当做了内联函数

有些大一点的函数就类中声明,类外定义,源码就这样搞的,所以声明定义分离还是有一定的道理的。

8.关键字auto

a.语法
int a=0;
auto b=a;
auto c=&a;cout<<typeid(b).name<<endl;//int
cout<<typeid(c).name<<endl;//int*

实际价值是为了简化类型很长的代码。

b.缺点
  • 不能做形参
  • 不能声明数组
  • 定义变量必须初始化 

c.特性
  • auto后加*或者&就是限定类型为指针或者是引用 
  • auto a=1,b=2;
    auto c=1,b=2.0;//报错

    同一行定义多个变量时,这些变量必须是相同的类型,否则编译器会报错,因为编译器是根据第一个类型进行推导,再用推导出来的类型定义其他的。

d.typedef的缺点(附加)
typedef char* pstring;
int main()
{const pstring p1;//报错,需要初始化const pstring* p2;//正确
}

 这里所说的缺点就是如果是const char* p1,就不会报错,因为const修饰的是p1指向的空间,可以不对p1赋初始值,但是使用typedef就不行了,这里会被误解为const char p1,const修饰的是p1,要对p1赋初始值。

9.范围for(c++11)

	int array[]={0,1,2,3};for(auto e:array)//自动依次数组中的数据赋值给e对象,自动判断结束,所以e的改{cout<<e<<" ";     //变不会改变数组的值,想改数组值用auto& e}cout<<endl;

c++11提供的语法糖,底层其实是迭代器,知道怎么使用就行(分号前是范围内用于迭代的变量,右边是被迭代的范围) 

这里auto加上了引用是因为数据量大且涉及深拷贝(以后还会介绍)。

10.关键字nullptr

c++里NULL(NULL是一个宏)被定义为0,识别出来是int,实际c++不定义应该是((void*)0)

总结:

只介绍了c++中一些常见的基础语法,精进需要结合后面的内容,毕竟只学习语法却不了解应用是学不好的,本文如有错误请指正并会及时回复。

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

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

相关文章

Matplotlib中的子图:规划绘图的指南和工具

导 读 我最近从事一个项目&#xff0c;需要在 matplotlib 中进行一些微调的子图和叠加。虽然我对制作基本的可视化感到很舒服&#xff0c;但我很快发现我对子图系统的理解没有达到标准。于是回到基础知识&#xff0c;并花了一些时间阅读文档并在 Stack Overflow 上搜索相关示例…

uniapp—day02

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a;给自己一个梦想&#xff0c;给世界一个惊喜。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章目录 WXML 和HTML区…

C语言——简易版扫雷

目录 前言 ​编辑 游戏规则 游戏结构的分析 游戏的设计 使用多文件的好处有以下几点&#xff1a; 游戏代码实现 框架&#xff08;test.c&#xff09; game函数&#xff08;test.c&#xff09; InitBoard初始化&#xff08;game.c&#xff09; Print打印棋盘&#xff08;g…

掘根宝典之C++迭代器简介

在C中&#xff0c;容器是一种用于存储和管理数据的数据结构。C标准库提供了多种容器&#xff0c;每种容器都有其独特的特点和适用场景。 我们知道啊&#xff0c;我们可以通过下标运算符来对容器内的元素进行访问&#xff0c;但是只有少数几种容器才同时支持下标运算符&#xf…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的商品识别系统(深度学习+UI界面+训练数据集+Python代码)

摘要&#xff1a;在零售行业的技术进步中&#xff0c;开发商品识别系统扮演着关键角色。本博文详细阐述了如何利用深度学习技术搭建一个高效的商品识别系统&#xff0c;并分享了一套完整的代码实现。系统采用了性能强劲的YOLOv8算法&#xff0c;同时对YOLOv7、YOLOv6、YOLOv5等…

Linux操作系统与Windows文件互传(FTP)

一、开启Ubuntu下的FTP服务 打开Ubuntu的终端窗口&#xff0c;然后执行如下命令来安装 FTP服务。 sudo apt-get install vsftpd等待软件安装完成后&#xff0c;用输入以下命令打开vsftpd.conf文件 sudo vim /etc/vsftpd.conf 找到下图的两个使能语句改成如图即可(记住保存后再…

Beans模块之工厂模块BeanFactoryAware

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

专题二 - 滑动窗口 - leetcode 904. 水果成篮 | 中等难度

leetcode 904. 水果成篮 leetcode 904. 水果成篮 | 中等难度1. 题目详情1. 原题链接2. 基础框架 2. 解题思路1. 题目分析2. 算法原理3. 时间复杂度 3. 代码实现4. 知识与收获 leetcode 904. 水果成篮 | 中等难度 1. 题目详情 你正在探访一家农场&#xff0c;农场从左到右种植…

比特币普通地址、隔离见证(兼容)、隔离见证(原生)、Taproot 地址傻傻分不清楚

我们在使用比特币钱包的时候&#xff0c;可以看到各种地址类型&#xff1a;普通地址、隔离见证&#xff08;兼容&#xff09;、隔离见证&#xff08;原生&#xff09;、Taproot 地址。 看得我们一脸懵逼&#xff0c;为什么会有这么多种类型的地址&#xff1f; 它们之间都有什么…

C语言 指针(4) qsort函数

目录 前言 一、回调函数 二、qsort函数 2.1 使用qsort函数排序整型数据 2.2 使用qsort排序结构数据 三、qsort函数的模拟实现 总结 前言 今天我们主要来学习一下C语言中的qsort排序函数。 一、回调函数 回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的指针&a…

spring启动时如何自定义日志实现

一、现象 最近在编写传统的springmvc项目时&#xff0c;遇到了一个问题&#xff1a;虽然在项目的web.xml中指定了log4j的日志启动监听器Log4jServletContextListener&#xff0c;且开启了日志写入文件&#xff0c;但是日志文件中只记录业务代码中我们声明了日志记录器的日志&a…

力扣98、530、501-java刷题笔记

一、98. 验证二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 1.1题目 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点…

[leetcode~dfs]1261. 在受污染的二叉树中查找元素

给出一个满足下述规则的二叉树&#xff1a; root.val 0 如果 treeNode.val x 且 treeNode.left ! null&#xff0c;那么 treeNode.left.val 2 * x 1 如果 treeNode.val x 且 treeNode.right ! null&#xff0c;那么 treeNode.right.val 2 * x 2 现在这个二叉树受到「污…

C#四部曲(知识补充)

Unity跨平台原理 .Net相关 只要编写的时候遵循.NET的这些规则&#xff0c;就能在.NET平台下通用 各种源码→根据.NET规范编写→(虚拟机)生成CIL中间码(保存在程序集中)→转成操作系统原代码 跨语言← 跨平台↓ Unity跨平台原理&#xff08;Mono&#xff09; c#脚本→MonoC#编…

MySQL 事务的原理以及长事务的预防和处置

transaction_isolation 隔离级别 读未提交 读提交 视图是在每个 SQL 语句开始执行的时候创建的 可重复读 视图是在事务启动时创建的&#xff0c;整个事务存在期间都用这个视图 串行化…

安装OneNote for Win10 | Win10/Win11

前言 PC端的OneNote分为2个版本&#xff0c;分别是Microsoft Store版本和Office版本&#xff0c;Microsoft Store版本即为OneNote for Win10&#xff0c;此版的OneNote有最近笔记功能&#xff0c;但检索功能不如Office版本&#xff0c;个人认为2个版本各有优劣。 但OneNote f…

【硬件基础】电容的选型

1、电容的理论基础 电容器的本质就是储能&#xff0c;充放电 根据作用可分为&#xff1a;滤波电容&#xff0c;旁路电容&#xff0c;耦合电容&#xff0c;退耦电容&#xff0c;自举电容 2、电容的取值 计算取值&#xff0c;查手册&#xff0c;经验取值 3、电容的选取 分为铝…

“删边“的并查集------反向并查集

目录 1.题目2.思路3.代码 默认大家都会并查集了 1.题目 小美认为&#xff0c;在人际交往中&#xff0c;但是随着时间的流逝&#xff0c;朋友的关系也是会慢慢变淡的&#xff0c;最终朋友关系就淡忘了。 现在初始有一些朋友关系&#xff0c;存在一些事件会导致两个人淡忘了他们…

AssetBundle打包与加载

官方文档 参照视频 1.AssetBundle打包 1.1设置资源的命名和后缀 命名只支持小写 1.2创建Editor文件夹&#xff0c;在里面创建编辑器打包AssetBundle的脚本 using UnityEditor; using System.IO;public class CreateAssetBundles {[MenuItem("Assets/Build AssetBun…

旅游景区公共广播 园区广播 公路服务区广播

旅游景区公共广播 园区广播 公路服务区广播 旅游景区公共广播 旅游景区公共广播(又称背景音乐)简称BGM&#xff0c;它的主要作用是掩盖噪声并创造一种轻松和谐的气氛&#xff0c;是一种创造轻松愉快环境气氛的音乐。掩盖环境噪声&#xff0c;创造与旅游景区相适应的气氛&#…