在上面我们介绍到了C++的输出流是cout<< 但在上面的代码中我们用了using namespace std,如果我们不加这串代码,能否继续用输出流cout<< ,如果不能用,该如何去解决呢:
• 使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式,C++的输⼊ 输出可以⾃动识别变量类型(本质是通过函数重载实现的,这个以后会讲到),其实最重要的是
C++的流能更好的⽀持⾃定义类型对象的输入输出
利用C++输入输出的最大的好处就是自动识别类型,不需要像C++那样整形用%d 字符型用%c什么的,所以很方便:
我们每次在写C++时都要包括头文件和std的命名空间展开。
输入输出可以一行输入输出多个。
输出是这样所以输入也可以自动识别:
上面有小数,那就有个疑问就是如何限定小数点后保留几位,在C语言中很简单就是(小数点+保留几位小数)即可,C++也可以但是很麻烦不建议,因为C++包含C语言。
四.缺省参数:
• 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参 则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。(有些地⽅把缺省参数也叫默认参数)
• 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
• 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省
值。
什么是缺省参数呢,在红框框里的函数参数可以看见,赋给了变量a一个初始值0,如果在调用函数时没有给初始值,这时用的就是默认给的初始值0,此时这个初始值0就叫缺省值,如果调用了函数并给了初始值那就用这个初始值。
什么是半缺省和全缺省呢:
全缺省就是函数里的所以参数全都给了初始值,而半缺省就是函数里的参数并没有完全给定初始值。
C++规定半缺省时必须从右往左,并且中间不能有间隔
下面是几个错误的样例:
这个就属于中间有间隔了,所以是错的
这个就属于从左往右了,也是错误的。
说完了给值,这里说一下怎么调用全缺省和半缺省的函数:
首先说一下全缺省的四种调用方式:
第一种就是不给初值,直接用缺省参数。 第二种就是只给一个初始值,函数的调用,缺省值给的顺序必须是从左到右并且不能跳跃给值,所以下面两种就不用分析了就是给值给了几个。
下面分析一下半缺省的三种调用方式:
半缺省三种调用方式,半缺省的缺省值是从右往左连续缺省,所以第一种就是给第一个变量的值,下面两种方式同理
看一下运行结果:
没给值就要缺省值,给值的就用给的变量值。
缺省参数的实际意义:
在栈中插入数据时,如果空间不够我们就需要来扩容,但此时扩容就得2倍2倍的扩,如果我们一开始就要放入1000个数据,我们就可以利用一个缺省参数,直接改参数为1000.:
如果不知道就给缺省值4,就很方便,在初始化栈的时候就把空间开辟完成了,下面就不需要去扩容了,就会大大提高效率。C语言就没有缺省参数每次加的时候都会去扩容就会减缓效率。
• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省
值。
就接着上面演示如果要存1000个数据,我们就只能在声明里给缺省参数,不能在函数定义里给缺省参数:
如果去运行就会报错重定义了,所以缺省参数不能在声明与定义中同时出现。
因为如果同时出现,如果你把数写的不一致,编译器就不知道到底要用哪个数去运行。
五.函数重载:
C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者 类型不同。这样C++函数调⽤就表现出了多态⾏为,使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同名函数的。
这就是函数重载的好处,虽然函数名相同但是参数类型不同,所以可以调用,这在C语言当中是会报错,编译不会通过的,这就是函数重载的好处。能很明显看出这时加法,就不用再像C语言那样去再重新定义另一个名称的函数。
像这两个函数是因为参数个数不一样构成函数重载但在调用时就会出问题,因为我不知道要调用哪一个函数。
但如果半缺省就可以运行成功:
第三种就是参数顺序不同构成的函数重载。
返回类型不同不构成重载函数。
一个经典的例题,也就是说构成函数重载必须要参数不同
可以是参数个数不同或者 类型不同
六.引用:
引用可以让C语言的指针更好利用。
引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间,它和它引⽤的变量共⽤同⼀块内存空间
在语法层引用是不会额外开空间的,跟变量共用一个空间。
类型& 引⽤别名 = 引⽤对象;
这四个变量名虽然不一样,但是地址是一样的因为只是给a取了别名罢了,就是同一个东西罢了,用的还是也同一块地址。
这里来调试一下,虽然只是给d++了但其实都是一个东西,所以都加加了。
1.引用的使用:
•
引⽤在实践中主要是于引⽤传参和引⽤做返回值中减少拷⻉提⾼效率和改变引⽤对象时同时改变被引⽤对象。
引用做返回值后面再介绍,这里就介绍一下引用传参的实践
这里就不用传地址了,rx就是x的别名,rx就相当于x,同理ry就相当于y,所以在函数里面的操作就算不传址也能改变x和y,rx和ry的改变就是x和y的改变。
这里改变的是变量的值就引用变量,如果我们想改变指针,就引用指针:
这里的引用就是引用的指针,改变了我们一开始用C语言写用二级指针去完成就很麻烦
单链表的实现:单链表专题-CSDN博客
2.引用的特性:
• 引⽤在定义时必须初始化
• ⼀个变量可以有多个引⽤
• 引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体
这里就不是引用,仅仅只是赋值,并且d的地址与其不一样,因为引用一个实体后,再不能引用其他实体。
3.const引用:
• 可以引⽤⼀个const对象,但是必须⽤const引⽤。const引⽤也可以引⽤普通对象,因为对象的访
问权限在引⽤过程中可以缩⼩,但是不能放⼤。(单纯的拷贝不存在权限的放大和缩小)
• 不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样⼀些场景下a*3的和结果保存在⼀个临时对象中, int& rd = d 也是类似,在类型转换中会产⽣临时对象存储中间值,也就是时,rb和rd引⽤的都是临时对象,⽽C++规定临时对象具有常性,所以这⾥就触发了权限放⼤,必须要⽤常引⽤才可以。
• 所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象,
C++中把这个未命名对象叫做临时对象。
• 可以引⽤⼀个const对象,但是必须⽤const引⽤。const引⽤也可以引⽤普通对象,因为对象的访问权限在引⽤过程中可以缩⼩,但是不能放⼤:
这个就属于权限放大了,因为原变量是cosnt变量,是不可以修改其数值的,但是现在引用却不是const变量了,导致现在权限被放大了所以这是会报错的。
这样就可以了,这就是权限的平移。
当权限缩小也可以运行,不会报错:
这里缩小的只是引用的rb,并没有影响b本身的权限,简单来说,b可以++,rb不可以++:
还有值得注意的是,cosnt可以给常量引用,而普通的引用不能引用常量:
运算符的引用也需要用const去引用,因为运算符运算结束是会产生临时变量,而临时变量具有常量型,所谓常量就无法改值,所以就不能有权限的放大和缩小,所以要用const去引用:
在这一步d给i发生了类型转换 也是隐式变量存储,会产生临时对象,只读不能写,所以要引用的话还必须是const引用,
所以这里引用的并不是d这个变量本身而是引用的d变成int类型的临时对象。
所以cosnt引用既能引用常量也能引用const类型的常量,也能引用临时对象。也就是说const引用的范围十分广泛。所以cosnt引用传参就非常有用,后面就会有印证。
4.指针和引用的关系:
C++中指针和引⽤就像两个性格迥异的亲兄弟,指针是哥哥,引⽤是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有⾃⼰的特点,互相不可替代。
• 语法概念上引⽤是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。
• 引⽤在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
• 引⽤在初始化时引⽤⼀个对象后,就不能再引⽤其他对象;⽽指针可以在不断地改变指向对象。
• 引⽤可以直接访问指向对象,指针需要解引⽤才是访问指向对象。
• sizeof中含义不同,引⽤结果为引⽤类型的⼤⼩,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte)
• 指针很容易出现空指针和野指针的问题,引⽤很少出现,引⽤使⽤起来相对更安全⼀些。