C和C++的区别

  1. 带有默认值的函数

C89标准中,c语言没有带有默认值的参数,c99之后才有

给函数默认值既可以在定义处,也可以在声明处,但只能给一次默认值

第一次声明时给最右边的参数一个默认值,第二次声明时给左边参数一个默认值也是合法的(vs2008中合法,但是vs2017中是非法的)

赋默认值必须从右向左依次赋值,在调用时,如果没有给实参,则把参数默认值压栈,也可以只传没有默认值的那个参数。

使用有默认值的函数可以提高效率(少一步汇编过程,节省一个mov指令的周期)

使用函数的默认值时相当于直接传递一个即时数

  1. Inline内联函数

我们在一个文件中定义了sum函数,想要在另一个文件中使用它,因此在另一个文件中对其进行了声明,这在编译链接时是没有问题的

但是如果在该函数的定义处加上inline关键字,你会发现系统报了一个“无法解析的外部符号”的错误。这是为什么呢?

内联函数不产生符号,在函数的调用点,把函数的代码全部展开(编译时完成)

这个过程和宏的使用很相似,但是宏替换是在预编译阶段就进行的,不进行任何的检查,只进行字符串的替换。因此可以把内联函数成为更安全的宏(类型检查,编译阶段)

内联函数 和 普通函数的区别

1·内联函数没有标准的函数栈帧的开辟和回退

2·内联函数仅在当前文件可见,不产生符号(一般定义在头文件中)

内联函数 和 static函数的区别

1·static函数有正常的栈帧开辟和回退的过程

2·static函数产生一个local的符号,内联函数不产生符号

3·都是仅在当前文件可见

注意:内联函数只在release版本起作用,在debug版本里面,也需要开辟和回退栈帧(方便调试)

  1. 函数的重载

C语言中函数的符号由函数名称产生,c++中函数的符号由函数名称和形参的类型和形参的个数共同产生

1·函数名相同,参数列表不同的函数称作一组重载函数,不能仅通过返回值不同来重载函数,因为产生符号和返回值无关

2·静多态 :函数重载   模板    动多态 :继承里面的多态(虚函数)

3·重载函数必须处于同一作用域下

C语言中允许在一个函数中声明另外一个函数

如图我们在主函数中对compare函数重新声明,这里我们只声明了int型参数的一个重载,可以看到第三个调用报错,这是为什么呢?

在c和c++中可以定义全局和局部的同名函数,但是在局部调用时,默认优先调用局部声明的函数 ,局部没有声明的情况下再去搜索全局的,这个例子中主函数里已经有了cmopare函数的声明,因此不会再去全局作用域中搜索,但主函数里声明的compare函数的参数是int型的,double型进行默认转换也可以调用int型参数的compare函数,但是在字符串比较时就会出错。

如果重载的时候把double类型参数的重载定义成float会出错,这是因为我们的浮点数默认类型为double型,主函数在执行compare(10.5,20.6)这句代码时,不知道要调用哪个重载函数,这是需要把实参的类型定义成准确类型(重载中存在的类型),在这里是compare(10.5f,20.6f)。

默认类型转换顺序(横向是无条件转换,纵向是当出现纵向两种类型比较时的转换顺序)

  1. C和c++之间的相互调用

由于c和c++产生的符号不同,要想直接调用会出错

C++调用c代码时可以加上extern “C”关键字,说明里面的符号是按照c语言的规则生成,如下

C语言调用c++如何实现?

把c++代码用大括号括起来,在前面加上extern “C”,这样的话,这段c++代码就会产生c语言的符号,就能被调用了

C++调用c的时候不用看到c的源代码,直接在c++声明处使用extern“C“,但是c调用无法看到源代码的c++比较麻烦,这时我们可以自己写一个c++文件,把要调用的函数封装起来

  1. const的区别

c语言中const是常变量,加上和不加唯一的区别就是长变量不能作为左值存在,但归根究底还是一个变量,c语言中const修饰的变量可以不被初始化,若不初始化则不能再给其赋值,不能用const修饰的变量作为数组的下标 (C89标准,C99以后同C++),

c++中const修饰的量是常量,必须初始化,可以作为数组的下标,编译时,所有使用常量名的地方全部替换成常量的值。当c++中的常量引用一个编译阶段不明确的值的时候,就会退化成常变量,此时不能再作为数组的下标。

如要在c++其他文件使用该文件中的常量,可以在定义处加上extern关键字,常量生成符号默认为local的,加上extern时则会产生一个global的符号。

  1. 引用

我们通过汇编代码可以发现,引用的本质其实就是一个常指针,指向不能改变。编译器对引用的处理和对指针的处理是相同的,引用相当于对一个指针解引用,引用变量的地址无法访问,都会转换成对指针的解引用操作,变成对所指向的变量的操作

1·引用变量必须初始化

2·初始化的值必须要能取地址(不能是一个即时数)

3·引用不能改变

4·访问引用变量,永远访问的是它所引用的内存

  1. const和一级指针的结合

 

我们先来看一下这四句代码里面哪个p都是常量?其实只有后面两个是常量,怎么区分呢?

首先要注意const和一级指针结合的时候会有两个方面,一个是她所修饰的类型,一个是她所修饰的表达式,const修饰的类型怎么判断呢,大家记住:const向左或向右遇到的第一个完整的类型就是const所修饰的类型,而表达式就是const右边的变量,在这里前两个const修饰的表达式是*p,第三那个修饰的是p本身,第四个有两个const,分别修饰*p和p。

Const修饰谁,谁就是常量,在这里前两个表达式中*p是常量,也就是说,指针p所指向的值不允许被修改(p的解引用),第三个是p本身是一个常量,即p所保存的地址不允许被修改(p的值),第四个p的值和p的指向的值都不允许被修改。

定义一个常量a,然后用一个整型指针指向他,这里为什么会出错?

判断一个const类型会不会出错,主要看const所修饰的常量的指针或者引用会不会被泄露出去,我们上面的操作相当于把一个常量的地址泄露给一个指针变量,常量不允许被修改,但是我们可以通过修改指针的解引用来修改常量的值,这当然是不被允许的。

修改成这样就可以了。

  1. const和&的结合

const和引用结合只有一种方式,即cosnt int &b(不能写成int & const b)。对于常量来说只能用一个常引用来引用该常量

上面代码中,第一行,用a去引用一个常量,这明显是错误的,因为常量无法取地址,而一个引用里面保存的就是其所引用的变量的地址,自然会出错。但是定义一个常引用去引用一个即时数却是可以通过编译的,这是为什么呢?

C++编译器在处理常引用引用一个即时数这种情况的时候,会生成一个临时量temp,它的值是这个即时数的值,而引用里面保存的就是这个临时量的地址

  1. const和二级指针的结合

这段代码中的三个二级指针q有什么不同?

第一个const修饰的表达式是**q,意思是**q这个二级指针解引用的值是一个常量,无法修改,但是q的指向和*q的指向都是可以改变的。

第二个const修饰的表达式是二级指针q本身,说明该二级指针本身就是一个常量,它里面保存的地址无法改变,即这个二级指针指向的一级指针不能改变。

第三个const修饰的是*q,说明*q是一个常量,不能被赋值,但是*q这个一级指针的指向可以改变

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值