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,一经查实,立即删除!

相关文章

使用Vue-Grid-Layout实现自定义工作台

前言 当代工作环境要求高度的个性化和定制化&#xff0c;因此&#xff0c;自定义工作台成为了一个热门的需求。Vue-Grid-Layout是一个强大的Vue组件&#xff0c;可以帮助我们实现自定义工作台的功能。在本篇博客中&#xff0c;我将向您介绍如何使用Vue-Grid-Layout来创建一个自…

找不到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;示例…

筛选可疑密码

题目描述 情报小组截获了若干个可疑密码&#xff0c;这些密码都是4位数。现在他们获得了一条最新情报&#xff1a;个位数与千位数的和 减去十位数与百位数的和&#xff0c;结果是一个正数。请你帮助情报组筛选目前的可疑密码。 输入 输入两行&#xff0c;第一行是&#xff1…

Codeforces Round 481 (Div. 3)

本场比赛也是没有考察什么算法重点在于思维模式 目录 A. Remove Duplicates B. File Name C. Letters D. Almost Arithmetic Progression E. Bus Video System F. Mentors G. Petyas Exams A. Remove Duplicates 要求我们从右边开始保留数&#xff0c;我们可以考虑的就…

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

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

c++ 语法函数

函数定义 返回值 函数名(参数列表){ 函数体 return xx } 无返回值 不需要return 返回值类型为 void int sum(int a,int b) {int sum a b;return sum; } int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n"…

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图像进行训练。使用这个模型,可以生成包括人脸在内的任何图像,因为有开源的预训练模型,所以我们也可以在自己的机器上运行它…

C#基础题

值类型和引用类型之间的区别是什么&#xff1f; 值类型在内存中存储实际值&#xff0c;而引用类型存储对对象的引用。值类型在栈上分配内存&#xff0c;而引用类型在堆上分配内存。值类型是不可变的&#xff0c;而引用类型是可变的。值类型的大小是固定的&#xff0c;而引用类型…

Java工具类库Hutool

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

类与对象

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

elementui 回到顶部报错

<template>Scroll down to see the bottom-right button.<el-backtop target".page-component__scroll .el-scrollbar__wrap"></el-backtop> </template> 使用element的Backtop 回到顶部组件的伙伴们&#xff0c;把官网代码复制到页面使用时…

定义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;文件的上传和预览必不可少。继上…