C++基础知识

目录

前言:

命名空间

命名空间的定义

命名空间的使用

c++输入与输出

缺省参数

函数重载

引用

引用的特性

常引用

引用的使用场景

引用做参数

引用做返回值

引用与指针的区别

内联函数

内联函数的特性


前言:

C 语言是结构化和模块化的语言,适合处理较小规模的程序;对于复杂的问题,规模较大 程序,需要高度的抽象和建模时, C 语言则不合适;为了解决软件危机, 20 世纪 80 年代, 计算机界提出了 OOP(object oriented programming:面向对象)思想 ,支持面向对象的程序设计语言 应运而生;
1982 年, Bjarne Stroustrup博士 C 语言的基础上引入并扩充了面向对象的概念,发明了一 种新的程序语言。为了表达该语言与 C 语言的渊源关系,命名为 C++ ,因此: C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计;

命名空间

由于变量 函数 类的名称存在于全局作用域中,会导致命名冲突;

使用命名空间的目的是对标识符的名称进行本地化,以防止命名冲突或名字污染

# include <stdio.h>
# include <stdlib.h> //stdlib.h文件中包含库函数rand()函数
int rand = 20;       //全局变量rand与stdlib.h文件中的库函数rand()发生命名冲突
int main()
{printf("%d\n", rand);return 0;
}
//代码运行结果 error C2365:"rand":重定义,以前定义是"函数"

命名冲突的场景:

1.  程序员定义的变量与库函数名相冲突;

2.  多人协作同一个大型项目,程序员之间发生函数名命名冲突;

命名空间的定义

程序设计者根据需要指定一些带有名字的空间域,将一些全局实体分别存放于各个命名空间中,从而与其他全局实体分割出来;

定义命名空间的关键字namespace

语法: namespce 命名空间名 { 命名空间成员 }

//命名空间名为Qspace
namespace Qspace 
{//定义变量int a = 10;//定义函数int Add(int x, int y){return x + y;}//定义类型struct ListNode{int val;struct ListNode* next;};
}

 命名空间嵌套定义

namespace Addspace
{int Add(int x, int y){return x + y;}//嵌套定义命名空间Subspacenamespace Subspace{int sub(int x, int y){return x - y;}}
}

 多个文件定义同名的命名空间,编译器最终会合成同一个命名空间中

//test.h文件
# include <iostream>
namespace MSpace
{int Mul(int x, int y){return x*y;}
}//test.cpp文件
# include "test.h"
namespace MSpace
{int Add(int x, int y){return x + y;}namespace Subspace{int sub(int x, int y){return x - y;}}
}
int main()
{int ret = MSpace::Mul(2, 3);printf("%d\n", ret);return 0;
}

命名空间的使用

方式一:加命名空间名称及作用域限定符(::) 即命名空间名 :: 命名空间成员名

namespace Qspace 
{int a = 10;int Add(int x, int y){return x + y;}struct ListNode{int val;struct ListNode* next;};
}
int main()
{printf("%d\n", Qspace::a);  //变量的访问方式int ret = Qspace::Add(2, 3);//函数的访问方式printf("%d\n", ret);struct Qspace::ListNode node = { 0, NULL };//结构体类型的访问方式return 0;
}

方式二:使用using将命名空间中某个成员引入 即using 命名空间名 :: 命名空间成员名

namespace MSpace
{int a = 10;int b = 20;
}
//using 命名空间名::命名空间成员名
using MSpace::a;int main()
{printf("%d ", a);return 0;
}

方式三 :使用using namespace 命名空间名引入即using namespace 命名空间名

using namespace 命名空间名 将整个命名空间展开,使得特定命名空间所有成员名可见,此时使用命名空间下的变量、函数不需要加作用域限定符,使得隔离失效;

namespace Addspace
{int a = 10;int Add(int x, int y){return x + y;}
}
using namespace Addspace;
int main()
{scanf("%d", &a);int ret= Add(2, 3);printf("%d\n", ret);return 0;
}

c++输入与输出

  • std是C++标准库的命名空间cout为iostream所定义的标准输出对象(控制台)(终端)cin为iostream所定义的标准输入对象(键盘),因此使用cout , cin必须包含< iostream >头文件及按命名空间使用方法使用std;
  • endl(endline)表示换行输出,相当于换行符,包含在<iostream>头文件中;
  • << 流插入运算符(与cout配合使用,可以将输出的变量或者字符串流入到cout中,cout负责输出到终端);  
  • >> 流提取运算符(与cin配合使用,将用户输入的值流入到某变量中);
  • cin以遇到空格键,tab键或者换行符作为分隔符,停止读取;
# include <iostream>
using namespace std;
int main()
{cout << "hello world!" << endl;return 0;
}

运行结果:

//cin遇到空格键 Tab键 Enter键停止读取
# include <iostream>
using namespace std;
int main()
{char a[10] = { 0 };cin >> a;cout << a << endl;return 0;
}

运行结果:

注:cout与cin可以自动识别变量类型

缺省参数

缺省参数是声明或定义函数时为函数的形式参数指定一个默认值(缺省值)

调用该函数时,如果没有指定实参则采用形参的缺省值,否则使用指定的实参;

# include <iostream>
using namespace std;
void Fun(int a = 10)
{cout << a << endl;
}
int main()
{Fun();   //没有传参时,使用形式参数的默认值Fun(20); //传参时,使用指定的实参return 0;
}

 运行结果:

缺省参数的分类

全缺省参数:函数定义或声明时,为该函数所有形式参数指定缺省值;

半缺省参数:函数定义或声明时,为该函数的部分形式参数指定缺省值,但是缺省值只能从右向左给值,必须连续给值;

# include <iostream>
using namespace std;
void Fun(int a = 10,int b=20,int c=30)//全缺省参数
{cout << "a="<< a ;cout << "b="<< b ;cout << "c="<< c << endl;
}
int main()
{Fun();Fun(1);Fun(1, 2);Fun(1, 2, 3);return 0;
}

 运行结果:

# include <iostream>
using namespace std;
void Fun(int a,int b=20,int c=30)//半缺省参数
{cout << "a="<< a ;cout << "b="<< b ;cout << "c="<< c << endl;
}

注:缺省参数不能在函数声明和定义同时出现,若声明与定义皆具有缺省参数,恰巧两个位置提供的值不同,此时编译器无法确定到底该采用那个缺省值,当声明与定义分离时,只能在函数声明处给出缺省参数

函数重载

函数重载:C++允许在同一作用域中声明几个功能类似的同名函数,但是要求同名函数的
形参列表(参数个数 参数类型 类型顺序)不同,返回值无要求;

//参数类型不同
int Add(int a, int b)
{return a+b;
}
double Add(double a, double b)
{return a+b;
}
//参数个数不同
int Fun(int a);
int Fun(int a,int b);
//形参类型的顺序不同
int Sub(int a, char b);
int Sub(char b, int a);

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

程序运行时,需要经历如下阶段:预处理 编译 汇编 链接,而在链接阶段会生成符号表,建立函数名与地址一一映射的关系,C语言链接函数地址时,采用函数名寻找函数定义,而对于同名函数无法区分函数地址,但是C++是通过函数修饰规则(如Linux下g++ 修饰规则:

_Z + 函数名字符个数+函数名+参数首字母)来区分,修饰后名字不同,自然支持了重载;

引用

引用不是新定义一个变量,而是 给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量 共用同一块内存空间
语法:   类型&  引用变量名(对象名) = 引用实体
//原变量与引用变量共用同一块内存空间
int main()
{int a = 10;int& pa = a;printf("%p\n", &a);printf("%p\n", &pa);return 0;
}

运行结果:

注:引用类型与引用实体必须是相同类型;

引用的特性

引用在定义时必须初始化;

int main()
{//正确示例int a = 10;int& pa = a;//错误示例int b = 20;int& pc;//编译时出错return 0;
}

一个变量既可以有多个引用又可以给引用变量继续取引用;

int main()
{int a = 10;int& pa = a;int& pb = a;int& pc = pa;cout << "a=" << a << endl;cout << "pa=" << pa << endl;cout << "pb=" << pb << endl;cout << "pc=" << pc << endl;return 0;
}

运行结果:

引用一旦引用一个实体,不能引用其他实体;

 int main()
{int a = 10;int& pa = a;int d = 1;// pa变成d的别名?还是d赋值给pa?pa = d;//pa的引用实体为a,让引用变量pa引用dcout << a << endl;return 0;
}

运行结果:

将d的值赋值给pa,又因为pa是a的引用,所以a的值间接变成了1;

常引用

int main()
{const int a = 10;int& b = a;//错误做法const int& b = a;//正确做法return 0;
}

变量a由于const修饰具有常属性,不可被修改;而引用变量b与原变量应具有相同属性,不能被修改,但是引用变量放大了权限,导致编译错误;

int main()
{//权限可以缩小int c = 20;const int& d = c;const int& e = 10;return 0;
}

变量c的属性为可读写,引用变量d的属性为可读,权限缩小并不会导致编译错误;

int main()
{int i = 10;double j = i;//整型提升double& rj = i;//错误做法const double& rm = i;//正确做法return 0;
}

当发生整型提升时,系统不是直接将其赋值给另外一个变量的,而是会创建一个常量区来存放变量提升后的结果,此时变量具有了常属性,一旦出现权限的放大,必然导致编译错误;

总结:类型转换(整型提升 截断)产生临时变量,临时变量具有常属性;

引用的使用场景

引用做参数

C语言阶段函数通过传址调用,实现通过形参修改实参,由于形参与实参数值上相同,空间上独立,所以实参是形参的临时拷贝;而引用变量在语法上与原变量共用同一块内存空间,若形参采用引用变量的方式,也可达到修改实参;

//指针方式
void Swap1(int* pa, int* pb)
{int tmp = *pa;*pa = *pb;*pb = tmp;
}
//引用方式
void Swap2(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}

引用做返回值

void Func()
{int c = 0;cout << &c << endl;
}
int main()
{Func();//Func()函数第一次调用结束,销毁第一次为func()函数所开辟的函数栈帧Func();return 0;
}

运行结果:

 由于空间可以重复利用,第一次调用Func()函数并为其开辟函数栈帧,并在函数栈帧中为变量c分配空间,当函数运行结束后,该函数所对应的栈空间由操作系统回收,但数据是否被清理是不确定的,当第二次调用Func()函数时,仍然在该地址处创建了c这个变量;

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)=" << ret << endl;return 0;
}

运行结果:

 ret其实指向的是c那块空间的地址,当c发生了变化,ret也就会随之发生改变;

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

运行结果:

当Add()函数运行结束后,由于static修饰的局部变量存放于静态区,出函数作用域并不会被销毁,此时可以引用返回,但是第二次调用Add()函数发生错误,原因为静态成员变量只会被初始化一次

总结:引用做返回值时,返回的数据必须由static修饰或者是存放于堆区的数据或者是全局变量等不会随着函数调用的结束而被销毁的数据;

引用与指针的区别

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

内联函数

宏是一种在程序中定义的简单代码替换机制,它们通常用于定义常量或执行重复性操作,与函数不同,宏是在编译时展开的,而不是在运行时调用;

宏的声明方式:

 #define name( parament-list ) stuff
//其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中
//宏函数
# define Add(x,y) ((x)+(y))
int main()
{int a = 10;int b = 20;int ret = Add(10, 20);cout << "ret=" << ret << endl;return 0;
}

宏的缺点:

1、容易出错,语法细节多;

2、不能调试(预编译阶段进行了替换);

3、没有类型安全的检查;

由于宏的缺点从而产生内联函数替代宏函数;

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

inline int Add(int x, int y)
{return x + y;
}
int main()
{int a = 10;int b = 20;int ret = Add(10, 20);cout << "ret=" << ret << endl;return 0;
}

内联函数的特性

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

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

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

相关文章

谈谈MYSQL主从复制原理

目录 概述 要点binlog日志 主从复制过程 总结 概述 MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。 MySQL 默认采用异步复制方式。从节点不用一直访问主服务器来更新自己的数据&#xff0c;数据的更新可以在远程连接上进行&#xff0…

Volatility3内存取证工具安装及入门在Linux下的安装教程

1-1. Volatility3简介 Volatility 是一个完全开源的工具&#xff0c;用于从内存 (RAM) 样本中提取数字工件。支持Windows&#xff0c;Linux&#xff0c;MaC&#xff0c;Android等多类型操作系统系统的内存取证。 针对竞赛这块&#xff08;CTF、技能大赛等&#xff09;基本上都…

瑞萨RZ/G2L核心板Linux Log目录文件详解

为了排除系统问题&#xff0c;监控系统健康状况以及了解系统与应用程序的交互方式&#xff0c;我们需要了解各log文件的作用&#xff0c;以G2L中yocto文件系统为例&#xff0c;在系统/var/log/目录下会存放记录系统中各个部分的log文件作用如下&#xff1a; 1. 文件详情 下图…

Ubuntu系统部署Inis博客并使用内网穿透发布到公网随时随地远程访问

目录 前言 推荐 1. Inis博客网站搭建 1.1. Inis博客网站下载和安装 1.2 Inis博客网站测试 1.3 cpolar的安装和注册 2. 本地网页发布 2.1 Cpolar临时数据隧道 2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09; 2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09;…

鸿蒙原生应用/元服务开发-Stage模型能力接口(二)

ohos.app.ability.AbilityConstant (AbilityConstant)一、说明 AbilityConstant提供Ability相关的枚举&#xff0c;包括设置初次启动原因、上次退出原因、迁移结果、窗口类型等。本模块首批接口从API version 9开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口…

matlab 最小二乘拟合平面(拉格朗日乘子法)

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。博客长期更新,爬虫自重。 一、算法原理 设拟合出的平面方程为: a x + b y &#

机器视觉系统选型-条形光源分类及应用场景

标准面光源 从平坦发光面照射漫射光 机械零件尺寸测量电子元件、IC的外形检测边缘缺陷检测服装纺织、食品包装检测 中孔面光源 从相机的同轴方向照射漫射光 金属零件缺陷检测金属外壳检测大面积电子元件的字符识别 平行面光源 照射平行度较高的漫射光玻璃瓶直径测量螺钉牙轮…

Android studio 离线配置gradle

Gradle Distributions Gradle Distributions 查看gradle 文件夹下 gradle-wrapper.properties文件中的distributionUrl 版本号 然后在上边网站下载对应需要的gradle对应版本 下载后复制到 gradle wrapper文件下&#xff0c;同时修改 distributionUrl 指向本地文件 然后同步就…

迷你型洗衣机好用吗?口碑好的四款小型洗衣机推荐

随着人们的生活水平的提升&#xff0c;越来越多小伙伴来开始追求更高的生活水平&#xff0c;一些智能化的小家电就被发明出来&#xff0c;而且内衣洗衣机是其中一个。现在通过内衣裤感染到细菌真的是越来越多&#xff0c;所以我们对内衣裤的清洗频次会高于普通衣服&#xff0c;…

轻量封装WebGPU渲染系统示例<47>- 多种光源(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/MultiLightsShading.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: export class MultiLightsShading {private mRscene…

STM32 DAC+串口

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、DAC是什么&#xff1f;二、STM32 DAC1.什么型号有DAC2. 简介3. 主要特点4. DAC框图5. DAC 电压范围和引脚 三、程序步骤总结 前言 提示&#xff1a;这里可…

Runtime

Runtime 概念&#xff1a; Runtime是一套底层纯C语言API&#xff0c;OC代码最终都会被编译器转化为运行时代码&#xff0c;通过消息机制决定函数调用方式&#xff0c;这也是OC作为动态语言使用的基础。Runtime的最大特征就是实现了OC语言的动态特性。 消息机制原理 在Objec…

代码随想录27期|Python|Day13|栈与队列|239. 滑动窗口最大值 (一刷至少需要理解思路)|347.前 K 个高频元素 (一刷至少需要理解思路)

239. 滑动窗口最大值 单调队列 滑动窗口中的队列一直保持出口大&#xff0c;入口小的顺序。&#xff08;图&#xff1a;代码随想录&#xff09; 1、每次有新的元素进入&#xff08;也就是滑动窗口移动后&#xff09;&#xff0c;都需要先和入口的元素比较大小&#xff0c;如果…

人体关键点检测2:Pytorch实现人体关键点检测(人体姿势估计)含训练代码

人体关键点检测2&#xff1a;Pytorch实现人体关键点检测(人体姿势估计)含训练代码 目录 人体关键点检测2&#xff1a;Pytorch实现人体关键点检测(人体姿势估计)含训练代码 1. 前言 2.人体关键点检测方法 (1)Top-Down(自上而下)方法 (2)Bottom-Up(自下而上)方法&#xff1…

ubuntu install sqlmap

refer: https://github.com/sqlmapproject/sqlmap 安装sqlmap&#xff0c;可以直接使用git 克隆整个sqlmap项目&#xff1a; git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev 2.然后进入sqlmap-dev&#xff0c;使用命令&#xff1a; python s…

静态代理IP搭建步骤,静态匿名在线代理IP如何使用?

静态代理搭建步骤 1. 确定需求 在搭建静态代理之前&#xff0c;需要明确自己的需求&#xff0c;包括代理服务器的位置、访问速度、匿名性、安全性等方面的要求。 2. 选择代理服务器提供商 可以选择自己购买服务器搭建代理&#xff0c;也可以选择使用云服务提供商的代理服务…

有趣的数学 用示例来阐述什么是初值问题二

一、示例 解决以下初值问题。 解决这个初始值问题的第一步是找到一个通用的解决方案。为此&#xff0c;我们找到微分方程两边的反导数。 即 我们能够对两边进行积分&#xff0c;因为y项是单独出现的。请注意&#xff0c;有两个积分常数&#xff1a;C1和C2。求解前面的方程y给出…

电工--半导体器件

目录 半导体的导电特性 PN结及其单向导电性 二极管 稳压二极管 双极型晶体管 半导体的导电特性 本征半导体&#xff1a;完全纯净的、晶格完整的半导体 载流子&#xff1a;自由电子和空穴 温度愈高&#xff0c;载流子数目愈多&#xff0c;导电性能就愈好 型半导体&…

28. Python Web 编程:Django 基础教程

目录 安装使用创建项目启动服务器创建数据库创建应用创建模型设计路由设计视图设计模版 安装使用 Django 项目主页&#xff1a;https://www.djangoproject.com 访问官网 https://www.djangoproject.com/download/ 或者 https://github.com/django/django Windows 按住winR 输…

docker build构建报错:shim error: docker-runc not installed on system

问题&#xff1a; docker构建镜像时报错&#xff1a;shim error: docker-runc not installed on system 解决&#xff1a; ln -s /usr/libexec/docker/docker-runc-current /usr/bin/docker-runc