由于之前学过C语言、java语言,所以这一版笔记不会把所有内容都记录下来,仅记录学习过程中不太清楚的,或者忘记的。比较基础的就不再进一步记录了。
1.关于字符串的补充
在之前的C语言学习中,已经详细的学习了C的各类数据类型,无论是整型还是浮点型,以及对应的作用范围,这里C++相较于大部分C的数据类型的声明,基本都还可以沿用,但是也多了一些优化。
类似于字符串的命名,我们既可以使用C风格下面的命名方式:
也可以使用C++中新增的风格命名方式:
(java中也有的一个关键字 string)
当然这里如果想使用string这个关键字的话,一些版本比较早的IDE会需要引用string 的头部文件。
补充一点知识:bool类型和char类型都是只占用一个字节
2.数据的输入和输出
作用类似于C语言的scanf、print关键字,从键盘中获取数据。关键字是:cin、cout
类似于java中的是
语法:cin>>变量、cout<<变量
注意其中的尖括号的朝向。
简单举几个例子,一个整型一个字符串型
回车输入。
另外需要特别注意的一个类型是bool型,如果键盘输入的bool型真为1,假为0,即便输入的是100最后结果也是1。
非0均为真
3.取模运算
第一点:取模运算,两个相除的除数不可以为0,这个是符合正常的数学逻辑。在linux通过gcc编译时通过了,但是实际运行后是得不到结果的,会报异常:
编译后运行结果为:
第二点:取模运算,两个小数是不可以做取模运算的。这里在linux通过gcc编译时都会报错。
编译报错为:
4.C++中,函数的形式参数列表中的形式参数是可以有默认值的。
以如下为例:
定义的函数func中为其形参b和c 设定了默认值,如果调用该函数时不传入指定值,则使用默认值,如果传入的指定值,那就使用传入的值来计算。
运行结果:
需要注意的问题1:
需要注意的是:如果形式参数的从某个开始有了默认参数,那么从这个位置往后都必须有默认值。
举个例子,在创建一个func2函数,我们给第一个参数a一个默认值,b,c不管。
编译会报错:
所以规定里,如果形式参数给默认值,则从这个参数开始后续的必须都要给默认值。
需要注意的问题2:
如果函数声明中有默认参数,函数实现就不能有默认参数。
举例来说:
通常来说,函数的声明和函数体的实现是分别放在头文件和.cpp文件中的,这里输出结果为3,没问题。
但是如果这样改一下,同时给函数声明和函数体加上默认值:
编译就会报错:
修改的时候:需要把声明的默认值去掉,或者把函数实现的默认值去掉,保留一个即可。
5.函数占位参数
C++中函数的形式参数列表可以有占位参数,用来做占位,调用函数时,必须填补该位置。
下面是一个正常的函数:
这样是正常编译,也可以正常运行出理想的结果。
我们修改一下func,改为:
再次编译,看一下对不对:
会发现这时候编译错误了,显示缺少了一个参数,由此我们可以得到结果:占位的参数也必须传递。
6.函数重载
函数名可以相通,参数不同,以提高复用性。
函数重载的满足条件:
1.同一个作用域下。
2.函数名相同。
3.函数参数不同(类型不同,或者个数不同,或者顺序不同)
注意:函数的返回值不可以作为函数重载的条件。
举个简单的例子
输出结果:
这样我们可以发现给定的参数不同,其会运行不同的函数体。
需要注意的事项:
有以下两个需要注意的地方:
引用作为重载条件,函数重载碰到函数的默认参数。
1.引用作为重载条件:
输出结果:
可以看到引用和const修饰的引用,是可以区分出来不同的重载函数的。在调用的时候给定对应的值即可。
碰到默认参数的问题:
这里我们编译,gcc就会给我报错了:
原因是存在函数重载的冲突问题。C++不允许定义两个参数相同或仅通过默认参数不同的重载函数。这是因为调用函数时会产生歧义,编译器无法确定应该调用哪个函数。
那么由此就可以知道,不能以默认参数来区分重载函数。
7.new操作符
C++中利用new 操作符在堆区开辟数据,有程序员手动开辟,手动释放,释放利用操作符delete。
基本语法示例:
编译输出结果:
上述示例我们用在堆区创建整型数据,new返回的是数据类型的指针,输出的结果为开辟空间的字节数,并且上述代码并没有释放,不释放这块空间一直存在,所以我们需要加上释放代码。
删除掉之后,我们在此输出一下,可以看到结果已经不是申请的空间大小了。这里就表明空间被释放了,这里访问就是非法访问了。
那如果是创建数组呢?应该如何创建。
尤其需要注意的是,在之前C语言中关于数组的笔记中,我们知道数组名只是指向第一个地址的位置,这里如果释放数组空间的时候如果仅仅这样来写:
就可能只释放了首地址的空间,后续的空间其实并没有释放,C++并未定义这个行为,所以为了保证正确性,数组释放时一定要记得带上[];
8.引用
引用也算是C++中一个比较重要的点,作用就是给变量起别名。
这里有一个变量a指向了一个4字节的空间内容为10;b也指向了这个4字节的空间。如果我要修改了b那么a的值是多少?
输出结果是:
那么我们可以发现这里修改了b的值后,变量a的值也被修改了,也就是说,无论是b还是a只是变量名不同,但是指向的内容是相通的,值要修改了这片空间的内容,a和b都会变成修改后的内容。
引用的用途主要集中在:函数参数传递以及函数返回值优化。
1.引用常用于函数参数传递,特别是在传递大型对象或复杂结构时,引用可以避免不必要的拷贝,从而提高性能。
2.函数可以返回引用,这在返回大型对象时非常有用,可以避免不必要的拷贝
需要注意的是:
1.引用必须在定义时初始化,并且不能更改指向的对象。
2.通过引用访问变量不需要解引用操作符(*)。
3.引用不能为 NULL,它必须始终引用一个有效的对象。
另外需要区分和指针的区别:
指针可以在任何时候初始化,并且可以在程序运行过程中更改指向的对象。通过指针访问变量需要解引用操作符 *
。指针可以为 NULL,表示它不指向任何对象。
示例:
在这个示例中,函数 modifyValue 接受一个整型引用,并将其值修改为 20。当 x 被传递给 modifyValue 时,实际上传递的是 x 本身,因此函数内的修改直接影响到 x。
错误示例,假设我现在想要使用引用传参数,同时要返回值引用,写了如下一个函数:
编译就会报错了
但是这个例子是有问题的,问题在于a + b 是一个临时值(临时变量),它在表达式求值结束后就不存在了,不能返回对临时值的引用。如果我们实在想使用引用传递以及返回值引用来实现两个数相加,应该怎么做呢?
可以给一个变量result,用它来存储计算结果。这样引用就不会指向临时变量,就不会报错了。