C++入坑基础知识点

当学习了C语言之后,很多的小伙伴都想进一步学习C++,但两者有相当一部分的内容都是重叠的,不知道该从哪些方面开始入门C++,这篇文章罗列了从C到C++必学的入门知识,学完就算是踏入C++的大门了。

1. 命名空间

写C的时候,偶尔可能不小心就和库函数冲突了,又或者当两个程序员以相同的名字命名变量或函数,就会发生冲突。C++就提出了一个很好的解决方案——命名空间

命名空间的关键字是namespace,定义方式如下:

【定义方式】

namespace N1
{int a = 3;int b = 4;
​int Add(int x1, int x2){return x1 + x2;}
​struct Node{struct Node* next;int val;};
​namespace N2{int c = 0;int d = 0;}
}

从示例中可以看出,命名空间中可以包含变量、函数、类型以及嵌套另一个命名空间

【使用方式】

1. 命名空间+作用域限定符

int main() {printf("%d\n", N1::a);return 0; 
}

2. using将命名空间中某个成员引入

using N1::b;
int main() {printf("%d\n", N1::a);printf("%d\n", b);return 0; 
}

3. using namespace 变量空间

using namespace N1;
int main() {printf("%d\n", a);printf("%d\n", b);return 0; 
}

2. 输入输出

其实C语言的printf/scanf在C++中还可以使用,不过C++有独有的输入输出方式,就是cin/cout

【使用说明】

1. 必须包含iostream头文件,注意是<iostream>

2. 需要使用命名空间std,因为cin/cout在其中的(日常练习可以这么做,但做项目的时候最好使用 std::cin 的方式展开)

3. 使用时要用<<流插入操作符/>>流提取操作符,不知道是什么没关系,看示例是怎么用的就行,cout用<<,cin用>>  

4. 变量之间也是用<<或>>连接,如果需要换行用endl

【示例】

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

【解惑】

我们有了printf和scanf为什么还要学习cin和cout呢,因为其可以自动识别变量的类型,相对来说就方便了很多,不用考虑太多。不过cin/cout相对于前者慢一些,在大量数据需要输入输出时就会有较大的时间差距。

3. 缺省参数

声明或者定义函数时为函数参数指定一个缺省值,当函数没有传递对应的参数时,就用缺省参数来代替(有点像备胎的感觉doge)

#include <iostream> 
using namespace std;void Func (int a = 10)
{cout << a << endl;
}int main()
{Func(); //输出10Func(100); //输出100return 0;
}

【分类】

全缺省参数:所有形参都加上了缺省参数

void Func(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;
}int main()
{Func(9, 8, 5);Func(9, 8);return 0;
}

半缺省参数:只有部分参数给缺省值

void Func(int a, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;
}//错误写法
//void Func(int a = 10, int b, int c = 30)
//void Func(int a = 10, int b = 20, int c)
//void Func(int a = 10, int b, int c)int main()
{Func(9);Func(9, 8);Func(9, 8, 5);return 0;
}

注意:

1. 半缺省参数只能从右往左给,不能跳跃给,也是为了避免传错参数,出现歧义

2. 缺省参数不能同时在定义和声明中出现,一般在声明中给

3. 缺省值必须是全局变量或常量

4. 函数重载

C++中允许在同一个作用域中出现参数列表不同(参数个数或类型不同)的同名函数,称这种现象为函数重载

【示例】

#include <iostream>
using namespace std;
​
//参数个数不同
void f1(int x, int y)
{cout << "void f1(int x, int y)" << endl;
}
​
void f1(int m)
{cout << "void f1(int m)" << endl;
}
​
//参数类型不同
void f2(int m)
{cout << "void f2(int m)" << endl;
}
​
void f2(double m)
{cout << "void f2(double m)" << endl;
}
​
//参数类型顺序不同,本质就是类型不同
void f3(int x, double y)
{cout << "void f3(int x, double y)" << endl;
}
​
void f3(double x, int y)
{cout << "void f3(double x, int y)" << endl;
}
​
int main()
{f1(10, 20);f1(10);cout << endl;f2(10);f2(1.0);cout << endl;f3(10, 1.0);f3(1.0, 10);
​
​return 0;
}

【原理】

C++的编译器会对函数进行修饰,一种函数变量类型对于一种编码,所以不同的变量类型或者个数对应不同的汇编代码,所以函数名相同并不影响其分别不同的函数。

而C语言中,相同的函数名是区分不开的。

(此部分需要对程序的翻译和执行部分有一定的了解,可以暂时跳过)

5. 引用

引用是对已经创建的变量起别名,操作符是&

【示例】

#include <iostream> 
using namespace std;int main()
{int a = 1;int& b = a;cout << a << endl;cout << b << endl;//打印结果都是1cout << &a << endl;cout << &b << endl;//打印出来是同一个地址,也就意味着在同一个空间return 0;
}

结果如下:

所以当其中一个加的时候,另一个也加,效果如下:

注意:

1. 引用和实体的类型要相同,鲁迅和周树人都是人

2. 引用在定义时必须初始化

3. 一个变量可以多个引用,也就是可以多个别名

4. 引用一个实体就不能再引用其他的实体,鲁迅是周树人的别名,就不能再用“鲁迅”代指张三了

5. 引用不能作函数局部变量的返回值,因为返回值的空间在退出函数之后就销毁了,而引用与它共用一块空间,所以此时为非法访问空间。当然,如果是全局变量/函数外局部变量/静态变量/堆上变量也是可以的作为返回值的。

​​​​​​​

【使用方式】

1. 输出型参数

#include <iostream>
using namespace std;
​
void Swap1(int& x, int& y)
{int temp = x;x = y;y = temp;
} //节省拷贝的空间,在传大的对象时对比更加明显
​
void Swap2(int* m, int* n)
{int temp = *m;*m = *n;*n = temp;
} //需要额外开辟一块空间存临时变量
​
int main()
{int a = 1, b = 2;Swap1(a, b);cout << a << " " << b << endl;int c = 1, d = 2;Swap2(&c, &d);cout << c << " " << d << endl;
​return 0;
}

2. 函数返回值(注意返回局部变量时不可用)

#include <time.h>
#include <iostream>
using namespace std;struct A
{ int a[10000]; 
};A a; A TestFunc1() 
{ return a;
}A& TestFunc2()
{ return a;
}int main()
{size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;return 0;
}

这效率,赢麻了!

有小伙伴又要问了,引用这么香,谁还用指针呀?

那我们就得来看看指针和引用的区别了:【面试考点】

语法:

  1. 引用是别名,不开空间,指针是地址,需要开空间存地址
  2. 引用必须初始化,指针可以初始化也可以不初始化
  3. 引用不能改变指向,指针可以(不可替代的关键)
  4. 引用相对更安全,没有空引用,但是有空指针,容易出现野指针,但是不容易出现野引用
  5. sizeof(引用为引用类型的大小,指针为地址的大小)、++(引用实体+1,指针偏移一个类型的大小)、解引用访问(引用不用解引用)等方面的区别

底层:

汇编层面上,没有引用,都是指针,引用编译后也转换成指针了

总结:C++的引用,对指针使用比较复杂的场景进行一些替换,让代码更简单易懂,但是不能完全替代指针,因为引用定义后,不能改变指向

【常引用】

如果我需要一个不可被修改的别名,就会使用到常引用

//代码一:正常引用(权限平移)
int a = 10;
int& ra = a;
​
//代码二:会报错,本来我设的变量不可被改,但是你的引用可以改,相当于给它的权限过大了
const int b = 10;
int& rb = b;
​
//代码三:常引用,相当于创建了一个不可修改的别名(权限缩小)
int c = 10;
const int& rc = c;//代码四:d转换成int需要生成临时变量,再将临时变量赋给rd引用,
//而临时变量是常量,所以rd要用常量引用,此代码没有const是编译错误的
double d = 3.14;
const int& rd = d;

6. 内联函数

一般来说,函数调用都会建立栈帧,而如果有方式可以避免栈帧的调用,可以大大提高运行的效率。

C++引入了一个关键字inline,以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开(函数调用替换为函数体),没有函数调用建立栈帧的开销,从而大大提升运行效率。

【示例】

inline int Add(int x, int y)
{return x + y;
}int main()
{int ret = Add(3, 4);cout << ret << endl;return 0;
}

其实没什么好说的,就是在函数前加上inline。

不过,编译器会判断此代码是否大小合适,如果比较大的话还是会建立栈帧,避免在调用处展开导致程序膨胀。

注意:

1. 不能是递归的函数,且最好规模较小频繁调用的函数。

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

【拓展】

【面试考点】如果在头文件中包含了一个函数的声明和定义,导致出现链接错误,该如何处理?

1. 声明和定义分离

2. 用static修饰函数,链接属性只在当前文件可见,不会进符号表(大函数)

3. inline修饰,没有进符号表,不会出现链接冲突

有小伙伴就要问了,好像C语言里的宏也可以做到类似的效果(不建立栈帧就能调用)呀?

但是宏也是有缺点的,详细的内容可看这篇文章-链接

在C++中,有很多设计都可以替代宏:const,enum,inline

7. auto关键字

在C++中,有的类型的名字会很长,所以很容易会出错,而这就引出了auto关键字

这个关键字的作用就是自动识别类型

当然,除了用在比较长的类型名上,还可以用于for循环,这个也是C++特有的

示例如下:

int main()
{int array[] = { 1,2,3,4,5 };for (auto& e : array){e *= 2;}
​for (auto e : array){cout << e << " ";}
​return 0;
}

上面这段代码等价于:

int main()
{int array[] = { 1,2,3,4,5 };for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++){array[i] *= 2;}
​for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); p++){cout << *p << " ";}
​return 0;
}

可见这里可以省去了不少的代码,不过要注意如果不是遍历数组就不能这么操作了

【注意点】

1. ​​​​​​​auto声明指针类型时,用auto和auto*没有区别,但用auto声明引用类型时必须加&

2. auto不能作为函数参数和返回值,也不能用来声明数组

8. 空指针nullptr

NULL可作常量0,也可作无类型指针的常量,

一般情况下,NULL会被编译器认为是0常量,但是我们想用它的时候往往是当作指针来用,为了避免会出现麻烦的情况,所以C++又设计了一个nullptr指针,就是表示指针空值,即(void*)0

这篇内容很多,可以收藏下来慢慢看~感谢大家的点赞和支持👍

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

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

相关文章

找不到d3dcompiler_43.dll,无法继续执行代码的原因分析与解决方法

在运行某些软件或游戏时&#xff0c;可能会遇到系统提示找不到 d3dcompiler_43.dll 文件的情况。这个特定的动态链接库文件 (dll) 是 DirectX 3D 编译器组件的一部分&#xff0c;对于许多现代软件游戏的正常运行起着不可或缺的作用。它的主要功能在于将高级着色语言编写的代码转…

零基础学Python之核心基础知识

1.Python入门简介 &#xff08;1&#xff09;什么是Python Life is short, you need Python&#xff01;人生苦短&#xff0c;我用Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言…

MySQL数据库入门(概念+使用)

目录 1. 数据库的概念 1.1 数据库的存储介质 1.2 主流数据库 2. MySQL的基本使用 2.1 链接数据库 2.2 服务器管理 2.3 数据库&#xff0c;服务器和表关系 2.4 简单MySQL语句 3. MySQL架构 4. SQL分类 5. 存储引擎 本篇完。 1. 数据库的概念 数据库是按照数据结构来…

【CSS】页面自适应屏幕宽度(响应式布局媒体查询-@media、弹性布局、网格布局和相对单位-vh/em/%)

【CSS】页面自适应屏幕宽度&#xff08;响应式布局媒体查询-media、弹性布局、网格布局和相对单位-vh/em/%&#xff09; 一、媒体查询&#xff08;media&#xff09;1、媒体类型2、媒体特征3、媒体查询语法4、示例&#xff08;1&#xff09;示例1&#xff08;2&#xff09;示例…

leetcode热题100.二叉树中的最大路径和

Problem: 124. 二叉树中的最大路径和 文章目录 题目解题方法复杂度Code 题目 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 …

pytorch_car_caring 排坑记录

pytorch_car_caring 排坑记录 任务踩坑回顾简单环境问题代码版本问题症状描述解决方法 cuda问题&#xff08;异步问题&#xff09;症状描述解决方法 任务 因为之前那个MPC代码跑出来的效果不理想&#xff0c;看了一天代码&#xff0c;大概看明白了&#xff0c;但要做改进还要有…

C语言指针学习 之 指针是什么

前言 指针是C语言中一个重要概念&#xff0c;也是C语言的一个重要特色&#xff0c;正确而灵活地运用指针可以使程序简洁、紧凑、高效。每一个学习和使用C语言的人都应当深入的学习和掌握指针&#xff0c;也可以说不掌握指针就没有掌握C语言的精华。 一、什么是指针 想弄清楚什…

末世智能毁灭机械

在一个遥远的星球上&#xff0c;AI和机器人在末世中扮演着重要角色。由于一场毁灭性的灾难&#xff0c;人类文明几乎被彻底毁灭&#xff0c;幸存者被迫在废土中艰难求生。为了重建家园&#xff0c;人类和机器人联手&#xff0c;利用智能机械技术开始了重建工作。 然而&#xff…

应用层协议 ——— HTTP协议

应用层协议 ——— HTTP协议 HTTP简介认识URL二、登录信息三、服务器地址四、服务器端口号五、带层次的文件路径六、查询字符串七、片段标识符urlencode和urldecodeHTTP协议格式HTTP请求协议格式HTTP的方法HTTP的状态码HTTP常见的HeaderHTTPS VS HTTP对称加密 VS 非对称加密 HT…

Stable diffusion使用和操作流程

Stable Diffusion是一个文本到图像的潜在扩散模型,由CompVis、Stability AI和LAION的研究人员和工程师创建。它使用来自LAION-5B数据库子集的512x512图像进行训练。使用这个模型,可以生成包括人脸在内的任何图像,因为有开源的预训练模型,所以我们也可以在自己的机器上运行它…

Java工具类库Hutool

这里写目录标题 一、简介二、包含组件三、常用功能演示2、时间工具DateUtil3、数字类工具NumberUtil4、身份认证工具IdcardUtil5、信息脱敏工具DesensitizedUtil6、字段校验工具Validator7、集合工具类CollStreamUtil 一、简介 Hutool是一个小而全的Java工具类库&#xff0c;通…

类与对象

面向对象的程序设计 面对对象的程序 类 类 .... 类 设计程序的过程&#xff0c;就是设计类的过程。 面对对象的程序设计方法&#xff1a; 1.将某类客观事物共同特点&#xff08;属性&#xff09;归纳出来&#xff0c;形成一个数据结构&#xff08;可以用多个变量描述…

定义HarmonyOS IDL接口

HarmonyOS IDL简介 HarmonyOS Interface Definition Language&#xff08;简称HarmonyOS IDL&#xff09;是HarmonyOS的接口描述语言。HarmonyOS IDL与其他接口语言类似&#xff0c;通过HarmonyOS IDL定义客户端与服务端均认可的编程接口&#xff0c;可以实现在二者间的跨进程…

SpringBoot+Vue实现各种文件预览(附源码)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;在笑大学牲 &#x1f39f;️个人主页&#xff1a;无所谓^_^ ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 项目运行效果 前言 在做项目时&#xff0c;文件的上传和预览必不可少。继上…

数字化转型:企业适应新常态的关键之举_光点科技

在全球商业环境不断演变和技术日新月异的背景下&#xff0c;数字化转型已经成为企业不可回避的课题。它不仅关乎企业的未来生存与发展&#xff0c;更是适应新常态、提升竞争力的关键之举。但是&#xff0c;数字化转型并非一夜之间可以完成的任务&#xff0c;它需要全面的策略规…

nosql数据库期末考试知识点总结

目录 1、什么是nosql数据库&#xff0c;它包括哪些 文档数据库 建数据 哪一种是最简单的 2、什么是文档数据库 3、创建mongodb时默认会建造三个数据库&#xff0c;是哪三个 4、mongodb支持的数据类型有哪些 5、它的常规语句有哪些 6、副本集和分片集有什么作用 复制 …

linux中vim的操作

(码字不易&#xff0c;关注一下吧w~~w) 命令模式&#xff1a; 当我们按下esc键时&#xff0c;我们会进入命令模式&#xff1b;当使用vi打开一个文件时也是进入命令模式。 光标移动&#xff1a; 1 保存退出&#xff1a;ZZ 2 代码格式化&#xff1a;ggG 3 光标移动&#xff…

JSP和JSTL板块:第一节 JSP追根溯源 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 JSP和JSTL&#xff1a;第一节 JSP主要内容 一、什么是JSP二、IDEA的JSP相关配置1.UTF-8编码2.JSP代码模板 三、JSP的底层是Servlet四、Jsp的注释1.显式注释2.隐式注释 五、Scriptlet : 写在Jsp里的java脚本段 一、什么是JSP JSP: Java Server Page。SUN 公司提供的动态…

查询、导入导出、统计性能优化的一些总结

目录 1、背景 2、优化实现 2.1查询数据表速度慢 2.2调别人接口速度慢 2.3导入速度慢、 2.4导出速度慢的做出介绍 2.5统计功能速度慢 3、总结 1、背景 系统上线后&#xff0c;被用户反应系统很多功能响应时长很慢。用户页面影响速度有要求&#xff0c;下面针对查询数据表…