绪论
从本章开始我们正式进入到C++的内容,对此如果没有学习过C语言的建议先将C语言系统的学习一遍后再来(已经更新完在专栏就能看到)。
话不多说安全带系好,发车啦(建议电脑观看)。
附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要
思维导图:

要XMind思维导图的话可以私信哈
知识点:
C++的关键字的含义和C语言中一样都是有特殊意义的名称,我们在创建变量的时候不能使用相同的名。
细节:
下面是C++中的63个关键字,我们不需要去死记,通过不断学习自然就记住了。

在C语言中会有命名冲突的问题,在c++中为了避免一个项目中不同程序员写的代码(或者程序员写的变量名和库函数的函数名)发生命名的冲突,就推出了命名空间这个概念来解决命名冲突这个问题。对此命名空间内可以定义变量、函数、结构体、再嵌套一个命名空间 ......
知识点:
域一般分为:全局域、局部域、作用域(C语言已讲)、命名空间域、类域
细节:
下面通过代码来展示不同的域:
namespace ZYK { int a = -1;//在命名空间的变量,就是命名空间域 } int a = 1;//全局域 int main() { int a = 0;//在局部变量中就是局部域,和局部变量非常类型 return 0; }
知识点:
他的意思和他的名字一样:
就是把一个命名空间进行了展开,直接展开到了全局域中,所以要注意的是如果全局域有和命名空间域相同的变量名时就会报错(命名不明确),对此我们反思到,在一般情况下我们加上这个命名空间就是为了防止这种情况,所以我们一般看情况展开(在一多人合作的项目中我们不能进行展开、而在日常自己练习和单独完成的项目我们可以适当的进行展开)
基本语法:
using + namesapce + 命名空间名来展开对应的命名空间
附:当同时定义了多个相同名的命名空间时,此时会将这几个相同的命名空间进行合并,同样也不能有相同的变量名
下面通过练习来实践:
练习:
1. 在有局部域和全局域以及命名空间域的同时,先执行全局域再执行命名空间域最后访问局部域:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
namespace ZYK
{
int a = -1;//在命名空间的变量,就是命名空间域
}
int a = 1;
int main()
{
int a = 0;
printf("%d\n", ::a);
printf("%d\n", ZYK::a);
printf("%d\n", a);
return 0;
}

2. 对于嵌套的来说其大体使用方法一样(嵌套的指定即可):
这里就不过多的去叙述了,直接通过代码来展示:
3. 展开命名空间:
namespace ZYK
{
int a = -1;
}
using namespace ZYK;
int main()
{
int a = 0;
printf("%d\n", ::a);
printf("%d\n", ZYK::a);
printf("%d\n", a);
return 0;
}

知识点:
std是C++的标准库的命名空间的域名,C++的标准库的定义和实现都放在了这个命名空间内(和C语言中的 stdio.h 这个头文件有点类似 在std中包含的则是C++标准库的函数)

细节:
上面我们知道了c++中有一个命名空间名std ,他其中包含了许多函数,所以为了使用一个命名空间内的函数。我们就有两种方法也就是域作用限定符来指定/展开命名空间域
但是要注意的是并不是展开/指定了就能使用该函数了,同样要先用#define包含头文件,再通过std来间接的访问函数。所以说这两样东西缺一不可。
练习:
1. cout、endl
一般来说cout 和 endl 是同时使用的,
cout:(可以大概的理解成我们程序的那个黑框框)可以将 << (流插入运算符) 流进来的进行打印
endl:其实可以大概的看成 \n
cout 相较于printf来说:他可以连续一行插入多个数据,并且可以自动识别类型
附:而cin流提取运算符(类似scanf)
练习使用方法如下:
第一种方法:
一个正常使用该cout、endl时我们需要加上的条件:
头文件:#include<iostream> 、 展开std命名空间
优点:可以能更加便捷的使用
缺点:同样直接把一个命名空间打开是一个非常危险的举动
第二种方法:
此时我们并没有去展开一个命名空间,通过指定访问的方法来实现
但是:不要忘记了头文件#include<iostream>
优点:没有了展开命名空间的风险
缺点:若要多次使用则会些冗杂
第三种方法(也是比较推荐的方法):
这种方法是将所要用到的进行单独的展开,我们可以在常用的对应进行展开,而不常用的直接使用第二种方法
头文件 #include<iostream>(不能省略)
附:cout的自动识别的展示、以及因为自动识别而导致的精度丢失的问题(缺点)
附:在c++中可以写c的语法,因c++是兼容c的(所以我们printf和cout混着使用)
知识点:
在函数的形参部分加上一个初始值(缺省参数),当你没传参数时就会用缺省参数,如果你传了参数那就正常的使用传来进的参数值。
细节:
当我们同时有多个形参时,对于缺省参数的使用情况大概和单个时的情况差不多但是要注意的是:
- 传参时是从左往右依次传上去的(所以从左往右的算传几个算几个,若没传就用缺省参数)
- 并且不可以跳跃的来传递实参
- 缺省参数必须是从右往左的确立的(即若一半是正常形参一半是缺省形参时,此时正常形参必须在缺省形参的左边,这种形参别称为半缺省型,反之全缺省)
当我们分源管理时我们应该在哪里写这个缺省参数呢:
缺省参数应该只写在函数的声明处(因为怕出现声明和定义不同的问题),而不是写在定义处
练习:
1. 缺省参数的具体应用:

2. 传多个参数时要注意的点
a.不能跳跃传参
b.从左往右传参的
c.半缺省:(缺省参数必须从右往左,因为我们传参是从左往右的)
知识点:
在C语言中我们无法同时使用多个相同函数名但类型不同的函数,所以c++就对这方面进行了优化,让同名当不同参数类型的函数可以正常使用
细节:
对于函数重载时的参数一般分为三类:
- 类型不同
- 类型的数量不同
- 类型的顺序不同
- 总结来说就是:两个同名的函数其函数类型不能对应相等即可
而对于为什么C语言不能对相同的函数名的函数进行函数调用而c++却可以:
是因为在编译链接阶段 创建的符号表中命名的函数命有区别 ,C语言是直接把函数名命名当成符号表,而c++在生成符号表时的命名规则并不是直接用函数名而是有不同的命名规则
因此对于C语言来说当出现两个相同函数名时,就会导致链接时冲突、
而对于c++来说就不会出现冲突因为类型的不同所以函数命名就会不同(在gcc环境下的函数名的命名规则是:_Z3funii 其中_Z是固定的 + 3 是函数名的字符个数 + 函数名 + 函数的类型 ii : 两个整形)
知识点:
引用不是新定义一个变量,而是给已存在变量取了一个别名,在语法层面上编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。(就像绰号,叫真名和绰号是一样的)
引用的基本语法:引用的对象的类型+&+引用名 =引用的对象
//整形
int a = 0;
int& b = a;//指针
int * ptr = NULL;
int*& rp = ptr;
细节(注意点):
- 在创建引用定义时必须初始化:int& b = a;
- 一个变量可以用多个引用(一个人在每个阶段都可能有不同的绰号,但都是指同一个人)
int main() { int a = 0; int& b = a; int& c = a; // b 、 c 都是a的引用 }- 只能一开始进行引用的初始化指定引用对象、后面无法进行修改。(后面修改也只是赋值操作)
- 引用做参数
- 输出型参数 ,像我们之前在C语言写链表来举例,当需要改变phead时就需要传一个二级指针,但此时我们用到了引用就不用再使用二级指针。
- 提高效率,因为引用的物理意义是一个变量的别名,在传参时并不用为其开辟栈帧所以可以提高一定的效率。
- 引用做返回值
- 但要小心,引用返回的对象不能在栈里面,否则当出栈帧时就会导致非法访问,一般用于静态区,堆区上的
- 可以修改返回值
- 提高效率,当引用做返回值的时候,返回的就是一个变量的别名,此时在传递回去的过程中就不需要创建临时变量(放到寄存器)的返回,这样就能减少损耗
练习:
1. 通过引用来进行数值的交换(在C语言中我们需要用到指针才能完成)
//指针时:void Swap(int * a, int * b)
void Swap(int& a, int& b)//此时的a 、 b 是参数的引用
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 10;
int b = 20;
cout << a << ' ' << b << endl;
Swap(a,b);
cout << a << ' ' << b << endl;
return 0;
}

知识点:
对常数的引用时要注意的点(此处主要讨论的是const修饰的常变量)
- 在引用时,引用的类型相对于引用对象的类型来说只能平移或者降低(注意看注释,若看不懂后面有一个附加知识点)
- 一种特殊情况:
附:当需要整形提升/截断时他们在赋值前都会先创建一个临时变量,把这个提升、截断后的值先放到这个临时变量(寄存器)内,再把这个临时变量的值放到所要赋值的空间中(这样就避免把被赋值的值改变)
就是因为一个临时变量具有常性,所以需要加上const来修饰
临时变量具有常性 ,同理对于函数返回时也是一样的,当我们返回一个临时变量时是有常性的所以需要用到常变量const来修饰
此时我们还需要注意的点是:当返回值是引用时就不会创建临时变量了。
知识点:
- 在语法层面上我们理解的是引用并不开辟空间,但是在底层来说其原理和指针一样也是需要开辟空间的(我们理解了解底层即可平时就记住语法层面 : 就像老婆饼里没老婆)
底层逻辑一样
- 指针和引用的区别
- 没有NULL引用这种概念,而指针有空指针的概念
- sizeof中指针和引用有不同,引用的结果就是引用对象类型的大小,而指针时地址的大小
- 引用和指针的加减不一样
- 有多级指针,没有多级引用
- 指针需要解引用,而引用操作系统自动处理了
- 引用比指针更加安全(指针可能会有野指针的问题)
知识点:
一种可以根据左边表达式自动推到出其类型然后定义给变量
具体就用实例来描述:
int main() { int x = 10; auto a = &x;//因为地址,所以auto是指针类型 auto* b = &x; auto& c = x; cout << typeid(a).name() << endl;//int * cout << typeid(b).name() << endl;//int * cout << typeid(c).name() << endl;//int (引用的类型不用加上&) *a = 20; *b = 30; c = 40; return 0; }此处的 auto 和 auto * 其实是一样的
附:typeid(变量名). name() 这个可以识别输入变量的类型
细节(注意点):
- auto的价值是:一般适用于对一些比较长的类型进行auto自动识别化
- 使用auto定义变量必须有初始化(在编译阶段编译器根据初始化表达式推倒出表示的类型,其实auto并不是一个类型,在编译后会将其改成实际的类型如#define定义宏类似)
- auto也可以一次性声明多个变量,但是这几个变量类型必须是相同的(因编译器只对一个类型进行推导)
- auto不能用在形参部分来识别类型(编译器无法对参数的实际类型进行推导)(c++14往后的可以作返回值)
- auto不能直接对数组进行声明
知识点:
对数组进行遍历
语法: for (数组类型 变量名 : 数组名)
细节(注意点):
当把一个数组传进函数时其本质是一个指针(数组名首元素地址)所以在该函数内是不能去使用这个范围for的
通过练习描述:
int main()
{
int a[] = { 1,2,3,3,4,5,6,7,8,9,10 };
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
cout << a[i] << ' ';
}
cout << endl;
for (auto x : a)// for (数组类型 语法for的变量名 : 数组名)
{
cout << x << ' ';
}
cout << endl;
}
此时只是依次将数组a中的数据拷贝给x(所以拷贝的无法改变其数组内容)
若想改变在数组a的值就需要加上引用 如下:

知识点:
内联函数的设立是为了减少一些重复创建栈帧的开销,以inline修饰的函数被叫做内联函数,该函数不会去开辟栈帧,会直接在调用内联函数的地方展开使用。(在C语言中这种简单重复使用的函数一般会用宏来实现,但宏也有其自己的缺点所以c++进行优化创造出来内联函数)
细节:
- 内联函数的具体展现:
当没有使用内联函数时:就会正常的去调用函数,开辟栈帧...
当使用内联函数后:调用内联函数的地方会直接展开使用(此时就没用call调用函数)。
- 内联函数对于编译器来说是一个建议性的操作,最后是否实现取决于编译器(对于编译器来说:如果是递归函数/比较长函数他们就不会同意变成内联函数)
- 注意对于一个较大的函数来说,不能使用内联函数,因为内联函数会导致程序的指令变多(直接正常调用此时指令就在函数内并不会变多,而内联函数会将函数展开就会导致指令反而变多,如:假如一个函数的指令是50个,然后又100处地方要调用这个函数,此时对于直接调用函数的指令就是100 + 50 ,假如是内联函数就变成了 100 * 50)
- 假如你要分源管理,此时内联函数不要声明和定义分离(因为内联函数不需要要调用就不会生成地址而这样就不会进入到符号表,若声明和定义分开就会导致链接错误找不到,直接就写定义即可)
在c++中NULL并不表示空指针而是表示为0(NULL实际是一个宏代表0),所以在c++11中就新引入了一个关键字表空指针nullptr
本章完。预知后事如何,暂听下回分解。
持续更新大量C++细致内容,三连关注哈
我希望将Favorite模型添加到我的User和Link模型。业务逻辑用户可以有多个链接(即可以添加多个链接)用户可以收藏多个链接(他们自己的或其他用户的)一个链接可以被多个用户收藏,但只有一个所有者我对如何为这种关联建模以及在模型就位后如何创建用户收藏夹感到困惑?classUser 最佳答案 下面的数据模型怎么样:classUser:destroyhas_many:favorite_links,:through=>:favorites,:source=>:linkendclassLink:destroyhas_many:favor
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile
我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。