掌握C和C++的区别

在学习C++之前,一般都会学习C语言作为基础,但这两类语言除了设计理念不同以外(C语言面向过程,C++面向对象),在语法上也是有些不同的。

一、形参带默认值的函数

在C语言中,函数的形参是不能带默认值的,而在C++中,我们经常可以看到函数中带着默认值,一般在类的构造函数中就会给定一些默认值。但在给定参数默认值的时候有以下限制:
1.默认值需要从右往左给,语法规定不能跳跃传实参;
2.当对函数参数给出默认值后再调用函数也是需要进行函数压栈的。因为一个函数没有参数它就没法调用,所以不会因为函数参数带了默认值就不进行压栈;
3.当给函数参数指定默认值后,可以继续传参来传入新的值,也可以不传值而直接使用默认值;
4.当传入的值不同时可能会影响其效率,因为在汇编层面上也许就会少一条mov指令,直接使用push指令;
5.形参给默认值时在定义和声明时都可以给,但从实际考虑的话建议在定义处给,但一个函数的同一个形参只能给一次默认值,且如果分两次给的话,出现的顺序一定是先右后左的。

二、内联函数

在C89标准以前C语言中没有内联函数,而在C++中有内联函数,内联函数的定义只需要在普通函数前面加一个inline即可,以下是内联函数的特性:

1.内联函数与普通函数的差别

1.普通函数的调用会有标准的调用开销,而内联函数则可以大大减少这种开销。

2.内联函数的处理

1.内联函数在编译时,在调用函数处会被替换成函数中的表达式;
2.鉴于内联函数的替换性质,故一般会将生成指令远小于函数调用开销时间的函数设置为内联函数,最简单的一条判断法则就是代码比较短;
3.使用inline修饰函数只是给编译器建议,并不是所有加了inline的函数都会在调用处展开,最终是由编译器决定是否展开的;
4.不可以内联的函数:例如递归调用的函数就不可以内联,因为编译器会在判断阶段直接否定掉是否内联这个函数。

3.内联函数和宏的区别

1.内联函数可以调试,而宏是不能调试的,但内联操作只在release版本下才生效,在debug版本中内联操作是不生效的;
2.内联函数不会产生意外的参数问题,宏定义的“函数”很容易产生参数的错误。

三、可重载的函数

1.C++为什么支持函数重载

在前面的博客说过C/C++的函数在编译阶段会生成符号,C++之所以可以支持重载,是因为C++生成函数符号时,会以它的函数名以及参数的类型共同生成符号,而C语言中生成符号则是只以函数名来生成符号的,所以只要参数的个数和类型不同,就可以达到函数重载的目的。而在C++中,函数重载也是实现静态多态的重要手段。

2.函数重载需要注意的点

1.由于作用域的关系,当一个被重载的函数在某个区域被声明时,可能会出现错误,因为作用域不同时,作用域外定义的重载函数会被隐藏,注意此点;
2.当函数的某些类型的参数前加上const和volatile关键字时,不能作为重载函数,因为即使加上了关键字,有些变量的类型还是不变的;
3.仅返回值不同不能称作重载函数,因为返回值并不参与函数生成符号。

3.C和C++之间函数的重用

既然C和C++的函数生成符号的规定不同,那么如果想在C语言代码中使用C++的代码该如何解决,反之又该如何解决呢?
1.当直接引用函数时是肯定会报出链接错误的,因为生成的符号不同,所以在链接阶段符号重定位时会发现找不到某些函数;
2.在C++中调用C函数时,在函数外部声明:extern“C”,即告诉C++编译器此函数是C函数,生成符号时使用C的符号生成规则来对此函数生成符号,如此在符号重定位时就不会找不到符号了;
3.在C中调用C++函数时,把C++源码括在:extern "C”中,也是告诉C++编译器此部分的代码按照C生成符号的规则来生成;
4.只要是C++编译器,都内置了__cplusplus这个宏,在源码中经常会看到“ifdef __cplusplus”这种预编译指令,就是为了避免C和C++代码不兼容。这种方式比“extern”灵活,毕竟extern只能使用在C++编译器中,而宏则可以在C编译器和C++编译器中识别。

四、const关键字

由于C++中const修饰的变量在编译时会被替换,所以就引发了一下几点不同:

C语言 C++
不可以做为左值(由于语法规定) 不可以作为左值(由于在编译时期会做替换)
可以不初始化 必须初始化(由于替换的原因,不能去替换一个没有明确值的值)
称为常变量(底层当做一个常量生成指令) 称为常量(也是由于在编译时期会做替换)
可以使用指针修改 可以使用指针修改

不过C++中当使用变量来初始化常量时,常量会退化成常变量,因为只有在运行时才能取得变量的值,所以在编译时期就没有被明确替换。

五、引用----&

C语言并不支持引用,它是在C++中新增的一种语法。

引用和指针的区别

1.由于引用需要被初始化,指针在定义时可以不初始化,所以在安全性方面,引用会比指针更好;
2.在底层生成的汇编指令上,定义二者是相同的,改变值时,获取地址,改变内存上的值也是相同的;所以在无法取值的量上是无法定义引用变量的;
3.引用只有一级引用,而指针可以定义多级;
4.指针可以直接指向数组,但是引用则需要定义引用数组来指向数组。

右值引用

左值引用即我们最经常使用的引用,左值就是有内存、有名字、可以修改的值,所以不能去对一个没有地址的量定义左值引用,除非进行常引用(底层产生临时量来保存右值,对临时量进行引用); C++11后增加了右值引用,可以对右值进行引用定义,指令上产生临时量然后直接引用临时量,且定义后的右值引用变量是一个左值。

六、动态管理内存----new和delete

C语言中使用malloc和free来动态申请释放内存,而C++中则使用new和delete。二者的区别如下:
1.malloc和new的区别

malloc new
C的库函数 是一个运算符
(类型指针)malloc(大小) new 类型 (大小)
malloc仅开辟内存 new开辟内存并初始化
malloc开辟内存失败返回空指针 new开辟内存失败抛出异常

new抛出异常时我们可以使用try-catch语句来捕获异常。
2.free和delete的区别

free delete
C的库函数 是一个运算符
free( p ) delete p
释放何种内存时都使用free 释放内存时需要视情况指定类型

3.new的种类

名称 使用方法
普通new int *p1=new int(20);
开辟失败不抛异常的new int *p2=new (nothrow) int;
定位new,在指定的data内存上初始化值 int *p4=new(&data) int(50);
开辟常量内存 const int *p3=new const int(40);

不积跬步无以至千里。

猜你喜欢

转载自blog.csdn.net/qq_45132647/article/details/105827485