C++:基础语法

一、命名空间

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

1.定义

       定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对 { } 即可, { } 中即为命名空间的成员。命名空间本质上定义的是域。命名空间可以嵌套,也可以定义其他的命名空间。在多个文件中,可以同时定义同名的命名空间,编译器会将这些命名空间进行合并。

namespace mynamespace
{int a;int b;
}

2.使用

       命名空间有三种使用方式:

       (1)加作用域限定符

       在C/C++中,不同域可以定义同名变量,但是局部优先。‘:’为作用域限定符,假如我们要访问全局变量,只需在变量前加一个‘::’符号即可。

       编译器若要查找一个函数,它的默认查找的顺序是:先局部,再全局域。它不会主动到命名空间去找,除非我们加上作用域限定符之后才会进去查找。

       上图中,编译器现在在局部查找a变量,没有进入命名空间中。不加作用域限定符,就打印0,当加上作用域限定符时,编译器才会到我们指定的命名空间去找。

       (2)直接展开命名空间

       当我们需要重复调用一个命名空间里面的函数时,每一次调用我们就需要指定一下命名空间,多少有点麻烦。我们可以使用下面一条语句:

using namespace mynamespace;

       这条语句意为展开命名空间,意在指示编译器可以进入到这个命名空间去查找。当使用了这条语句之后,查找的优先级:局部>全局>=命名空间。在全局和命名空间同时存在同名函数或变量时,展开了命名空间之后,相当于把命名空间里面的东西释放到了全局中,如果之前全局域中存在了同名函数,那么就会报错。

       当两个命名空间同时展开时,若两个命名空间同时存在同名函数或变量时,编译器就会报错。因此,展开全部的命名空间是有风险的。

       (3)展开指定成员

       那么我们可以使用第三种方式:指定展开某一个。

using mynamespace::a;

       这条语句意为只展开某一个函数或变量,之后调用它时就不需再指定了。

       这种方法解决了直接展开命名空间时可能会引起的命名冲突的问题。

二、C++输入和输出

       在C语言中,我们使用printf、putchar、scanf等函数在屏幕上输出、输入数据,它需要包含stdio.h这个头文件,但是在C++中,我们使用cin、cout来输入、输出数据。

       其中c为console(控制台)的缩写,out为输出的缩写。在C++中,‘<<’这个符号为“流插入操作符”,endl 为 end line 的缩写,意为换行。在C++中,它多了许多智能的特性,编译器会自动识别变量的类型。当我们想要使用 cout 时,直接使用会报错,因为它在 iostream 中被封装到了一个名为 ‘std’ 的命名空间中。我们个人写代码时,可以直接将std展开,因为没人会和我们起冲突。但是在项目中,多个人参与进来时,尽量不要随意全部展开命名空间。

       当我们想要输入一些数据时,可以使用cin,意为从控制台中提取数据。‘>>’为流提取操作符。

       它的操作顺序是从左到右,输入两个数分别放在对应的变量中。

       当然我们也可以使用 printf 等C语言中的函数,iostream中也定义了这些函数。

三、缺省参数

       在C++中,对函数传参时也和C有所不同。它引入了一个新特性,我们可以不对它传值,那么编译器就会使用你默认设置的值。

       这个默认的值是在设计函数接受参数时设置的。当然也可以缺省多个值

       有一点就是不能跳跃着传参,也就是不能传a和c不传b,不能将b空过去,这样编译器会报错。上面是全缺省,也可以半缺省,但是必须是从右往左缺省,否则在调用的时候就会产生歧义,编译器不知道要将值传给谁。

       缺省参数在定义和声明不能同时出现。它只在声明处给。

四、函数重载

       在C语言中,在同一作用域是不允许同名函数出现的。但是在C++中,它可以在同一作用域中出现同名函数。它的名字可以相同,但是它的参数类型、参数个数、参数顺序需要不同,与参数名无关,当参数相同时,参数名不同,这两个函数不构成重载。当我们输入不同的参数时,编译器会自动去匹配参数类型然后调用相应的函数。若两个同名函数定义在了两个命名空间中,我们把这两个命名空间展开,调用这两个函数时,编译器会报错。因为两个函数不在同一个作用域中,不构成重载关系,编译器不会去匹配他们的类型。

       那么为什么C语言不支持重载呢?

       本质上来讲,是编译器对函数名的修饰不同。在C语言中,编译器不对函数名进行修饰,直接通过函数名来匹配。而在C++中,编译器会根据参数的不同对函数名进行不同的修饰,它们的名字可以相同,但是对它们进行的修饰不同,也就是说,在编译和连接之后,它们已经变成了不同名的函数。不同的编译器对函数名的修饰规则不同。

五、引用

1.引用的定义及使用

       在C++中,引入了引用的概念。引用与指针类似,但又不同于指针。

int main()
{int a = 0;int* b = &a;//指针int& c = a;//引用return 0;
}

       在第二条语句中,‘&’为取地址符,‘&a’表示取出变量a的地址,它是在C语言中使用的,而在C++中,它仍然可以使用。但是在C++中,‘&’还有另一个用法是引用,简单来说就是取别名。我们对c操作,实际上就是对a操作。它与指针的区别是不需要再添加解引用操作符 ‘ * ’ 了。它不仅可以对整形、浮点型变量取别名,也可以对指针变量取别名。

int*& e = b;

       对a的任意一个别名取地址,取到的都是a的地址,也就是说a的别名和a的地址都是相同的,a的别名是c,也可以对c取别名,也可以对c的别名取别名,本质还是a。

       在链表的学习中,有许多的函数需要传递二级指针,使用起来不太方便,那么我们就可以给指针取别名传给函数,就不需要再解引用二级指针来改变一级指针的值了,直接改变别名的值即可。

       引用一旦引用了一个变量,就不能再改变引用的对象。它没有空引用的概念。

2.引用和指针变量间引起的权限问题

       要注意,最初创建的变量的权限是最大的,如果最初创建的变量为可读不可写,那么它的引用的权限是不能大于它所引用的变量的,它最多只能可读可写。

        如图,我们使用b来引用经过const修饰的变量a,出现了报错,这就是权限的放大,引用的权限超过了它所指向的变量。a所引用的值是不能改变的,而b却可以改变,这就是权限的放大。

       当我们给b前面加上const时,此时b与a的权限相等,不会报错。

       指针也是如此,当我们写出下面的代码时,也会报错。

int main()
{int a = 0;const int* b = &a;int* c = b;return 0;
}

       这种也是权限的放大,const修饰的是指针指向的值,这个指针指向的值不能改变,而指针变量c也指向了这个值,却可以通过解引用的方式来修改,是权限的放大,因此编译器会报错。

       若const修饰的是整型变量,它不会引发权限放大的问题。

int main()
{const int a = 0;int b = a;b++;return 0;
}

       const修饰的是a的值,a的值不能被改变,但是不影响a赋值给b,b的值怎样改变与a无关,它们分别存储不同的空间,它们的改变不会相互影响。

       来看下面一段代码

       我们又创建了一个变量c来引用a,然后通过c来改变a,这时发现b的值也改变了,并且没有报错,这是因为const限制的只是它修饰的变量,即不能通过b来改变,但是可以改变c的值来间接改变b的值。

       来看下一段代码:

int main()
{double a = 13.14;//const int b = a;int& c = a;
}

       这段代码也是会报错,属于权限的放大。因为a在赋值给b时,由于类型的不同,复制之前就要先做类型转换,而类型转换具有常性,相当于经过了const修饰,这时候引用经过const修饰的变量,就是权限的放大。

       引用与指针的不同点:

       1.在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

       2.引用在定义时必须初始化,指针没有要求。

       3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体。

       4.没有NULL引用,但有NULL指针。

       5.在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
位平台下占4个字节)。

       6.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。

       7. 有多级指针,但是没有多级引用。

       8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理。

       9. 引用比指针使用起来相对更安全。

六、内联函数

       在一些函数中,需要调用许多次其他小函数,比如在排序中,要排几千万个数据,就要调用几千万次到几亿次的交换函数,但是每一次调用都要开辟对应的栈帧,开辟栈帧又是有消耗的,在C++中,有了内联函数的概念,它的意思是就是像交换函数这种小的函数但是需要调用的次数非常多,那么就直接将它展开在调用它的函数中,省去了开辟空间的消耗。它与C语言中的宏类似。但是它是由编译器自动实现的,C语言中还需要我们自己去实现一个宏函数,宏函数的实现很困难并容易出错,内联函数就很好的解决了这一点。

       特性:

       1.它是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。

       2.对于编译器而言只是一个建议,不同编译器关于内联函数实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用内联函数修饰,否则编译器会忽略内联函数特性。

       3.不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。
 

七、auto关键字(C++11)

       auto是一种能够自动推到变量类型的关键字,当一个变量的类型难以拼写时,就可以使用auto代替。

int main()
{std::map<std::string, std::string> m{ { "apple", "苹果" }, { "orange","橙子" },{"pear","梨"} };std::map<std::string, std::string>::iterator it = m.begin();while (it != m.end()){//....}return 0;
}

       std::map<std::string, std::string>::iterator 是一个类型,但是该类型太长了,特别容易写错。

直接将它换成auto,非常方便。

       也可以使用typedef来给类型取别名, 但是也有缺陷。

       使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

       使用细则

       用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&。

       auto*指定了它的对象必须是指针。

       当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

       auto不能推导的情况

       1. auto不能作为函数的参数
       2. auto不能直接用来声明数组
       3.auto在实际中最常见的优势用法就是C++11提供的新式for循环,还有lambda表达式等进行配合使用。

八、基于范围的for循环(C++11)

       对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范
围内用于迭代的变量,第二部分则表示被迭代的范围。

int main()
{int array[] = { 1, 2, 3, 4, 5 };//使用auto、int都可以,auto只是自动推导类型。for (auto e : array)cout << e << " ";return 0;
}

       范围for循环不能改变数组中的值,范围for循环是将数组临时拷贝一份然后遍历这个临时拷贝的数组。改变这个临时数组并不能改变数组中的值。

       注意:

       1.与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。
       2.for循环迭代的范围必须是确定的,对于数组而言,就是数组中第一个元素和最后一个元素的范围,即不支持在函数中对传过来的整形指针使用范围for遍历;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。

       3.它只支持从头到尾遍历数组。

十、指针空值nullptr(C++11)

       NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

       可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:

void f(int)
{cout<<"f(int)"<<endl;
}
void f(int*)
{cout<<"f(int*)"<<endl;
}
int main()
{f(0);f(NULL);f((int*)NULL);return 0;
}

       程序本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖。

       在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void*)0。

       注意:
       1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入
的。

       2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。

       3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

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

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

相关文章

lacp的详解

LACP&#xff08;Link Aggregation Control Protocol&#xff09;是一种用于在网络中组合多个物理链路以增加带宽和冗余的协议。它是IEEE 802.3ad标准中定义的一种链路聚合技术。 LACP允许将多个物理链路绑定成一个逻辑链路&#xff0c;称为聚合链路或聚合组。这个聚合组可以提…

【C++】一篇文章带你深入了解list

目录 一、list的介绍二、 标准库中的list类2.1 list的常见接口说明2.1.1 list对象的常见构造2.1.1.1 [无参构造函数](https://legacy.cplusplus.com/reference/list/list/list/)2.1.1.2 [有参构造函数(构造并初始化n个val)](https://legacy.cplusplus.com/reference/list/list/…

上位机图像处理和嵌入式模块部署(树莓派4b开机启动脚本)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 编写好程序之后&#xff0c;一般要求程序开机启动后就可以运行。所以这个时候&#xff0c;我们一般就会把程序流程放在开发板的启动脚本当中。如果…

Android 8.1 删除Launcher桌面搜索框

Android 8.1 删除Launcher桌面搜索框 最近接到项目反馈&#xff0c;要求删除Launcher桌面的搜索框&#xff0c;具体修改参照如下&#xff1a; /vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/config/BaseFlags.java public static final b…

开源大模型应该怎么选?

文章目录 前言为什么选择开源模型而不是商业模型?开源模型对比Llama 2Mixtral 8x7BZephyr 7BSOLAR 10.7BCode Llama 专用 Vs. 通用生产环境部署LLMs 的注意事项 前言 在过去的一年里&#xff0c;人工智能领域不断涌现出各种大语言模型(LLMs)&#xff0c;每个模型都在不断突破生…

代码随想录算法训练营day1 | 704. 二分查找、27. 移除元素

数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合。 因为数组的在内存空间的地址是连续的&#xff0c;所以我们在删除或者增添元素的时候&#xff0c;需要移动其他元素的地址。 那么二维数组在内存的空间地址是连续的么&#xff1f;不同编程语言的内存管理是不…

SpringBoot之@Conditional衍生条件装配详解

文章目录 ☃️前言☃️简介☃️示例❄️❄️ConditionalOnProperty❄️❄️ConditionalOnClass❄️❄️ConditionalOnBean❄️❄️自定义条件 ☃️SpringBoot源码中使用☃️总结 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客…

pET-28a(+)是什么,怎么看?-实验操作系列-1

01 典型的pET-28a()质粒遗传图谱 02 元件解读 Origin复制子&#xff1a;ColE1/pMB1/pBR322/pUC ori——起始载体的复制&#xff1b;f1 ori——f1噬菌体复制子&#xff0c;显示正义链合成方向。The origin of replication&#xff0c;由复制起始位点和相关调控元件组成&#xf…

Midjourney-01 初试上手 注册使用并生成你的第一张AI图片 详细流程 提示词 过程截图 生成结果 付费文生图的天花板!

背景介绍 Midjourney是一款基于人工智能技术的绘画软件&#xff0c;利用深度学习算法来辅助用户进行绘画创作。这款软件能够通过用户输入的文本描述生成图像&#xff0c;支持多种生成方式&#xff0c;包括文字生成图片、图片生成图片和混合图片生成图片。 图像生成方式&#…

Vscode根据Makefile文件使用make编译程序配置文件launch.json,task.json

视频介绍: VsCode使用make编译程序配置_哔哩哔哩_bilibili task.json: 2024年4.20 ctrl shift b 编译 {"version": "2.0.0","tasks": [{"label": "build_suricata","type": "shell","command…

【智能算法】蜉蝣算法(MA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2020年&#xff0c;K Zervoudakis等人受到自然界蜉蝣交配繁殖行为启发&#xff0c;提出了蜉蝣算法&#xff08;Mayfly Algorithm, MA&#xff09;。 2.算法原理 2.1算法思想 MA灵感来自蜉蝣交配…

python 文件打包(使用pyinstaller)

PyInstaller是一个流行的Python打包工具&#xff0c;它可以将Python代码打包成可执行文件&#xff0c;使得你可以在没有安装Python解释器的环境中运行你的应用程序。&#xff1a; 安装 使用pip命令来安装PyInstaller。在终端或命令提示符中运行以下命令&#xff1a; 打包 先…

如何高效的压缩GIF图片?一键搞定GIF动图压缩 就是这么简单

一&#xff0c;引言 压缩GIF动图是一个常见的需求&#xff0c;无论是在社交媒体上分享动态表情&#xff0c;还是在网页设计中添加动态元素&#xff0c;GIF动图都扮演着重要的角色。然而&#xff0c;过大的GIF文件大小可能会导致加载速度慢&#xff0c;影响用户体验。因此&…

linux 驱动-匹配1 (platform_bus_type)

目录 匹配入口 匹配顺序(platform_match ) 方式1: 方式2&#xff08;重点&#xff09; 方式3 方式4 (重点) 匹配入口 driver_match_device 实际调用platform_match driver_match_device(drv, dev);static inline int driver_match_device(struct device_driver *drv,str…

代码随想录学习Day 30

860.柠檬水找零 题目链接 讲解链接 思路&#xff1a;需要找零的情况是顾客支付10元或20元&#xff0c;尤其是支付20元时需要考虑找零的方式&#xff0c;此时可以选择找零3张5元或者一张10元一张5元&#xff0c;按照贪心算法的思路来看&#xff1a; 局部最优&#xff1a;在找…

常见的数据抽取工具对比

1.什么是ETL? ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&#xff08;transform&#xff09;、加载&#xff08;load&#xff09;至目的端的过程&#xff0c;是数据仓库的生命线。 …

中红医疗:纷享销客CRM系统如何助力​数字化“狂飙”

纷享销客深耕 CRM 多年&#xff0c;可以顺畅打通 CRM 和 ERP 系统客户资源池&#xff0c;将金蝶苍穹平台的物料、产品基础主数据作为档案同步到纷享销客&#xff0c;以便商务维护好产品及库存。 纷享销客通过成熟的集成方案提高系统耦合性&#xff0c;让销售实时获得新产品及营…

鸿蒙开发模拟器的坑, No Devices

问题 我已经安装了模拟器&#xff0c;并且模拟器已经运行了 在Device Manager页面开启模拟器 No Devices 但是这里没有模拟器的选项 解决 添加环境变量 下面步骤 1、清除用户数据 2、 关闭Device Manager 3、 关闭ide 重启ide、开启模拟器 看到有模拟器的选项了

目标检测算法——YOLO-Word——算法详解

一、概述 1、是什么 是一个目标检测器,通过结合CLIP文本编码器,拥有了开放检测(推理时识别训练时没有的目标)的能力。作者实验证明ap 指标上 zero shot能力YOLO-world L接近专门训练过的YOLOv6-8 S 模型的能力,finetune 后YOLO-world 均能提升8个点左右。 2、亮点 将文章…

LangChain入门指南:构建高可复用、可扩展的LLM应用程序 PDF书籍分享

今天又来给大家推荐一本大模型方面的书籍<Langchain入门指南>这本书专门为那些对自然语言处理技术感兴趣的读者提供了系统的LLM应用开发指南。全书分为11章&#xff0c;从LLM基础知识开始&#xff0c;通过LangChain这个开源框架为读者解读整个LLM应用开发流程。 下载当前…