C++基础之C与C++的联系和不同(三)

C++和C语言还有一些不同。

1、关于函数的参数

C语言有一些不好的使用方式。比如:如果一个函数没有参数,那么这个函数可接受任意个参数。如下代码可以编译通过:

void func(){}

int main()
{
	func(12,13);
	return 0;
}

C语言中无参函数是用void填充的,如:void func (void) {}。而且C语言中函数参数是可以没有类型的。

在C++中,如果函数没有参数,认为是无参函数,不可以传参,如void func () {}等价于void func (void) {}。C++中函数参数必须要有类型。


2、新的数据类型(bool类型)

bool类型的变量值只有两种,true和false,true值为1,false为0。用0来表示false,非0表示true。

要注意的是,在运算中,bool类型变量只要值不为0,就是1。bool类型变量可以自加操作(++),但不能自减操作(--)。如:

bool b = true;
int a = 1;
b = a - 2;
b++;
printf ("b = %d\n",b);


编码中,我们一般用这种方法判断真假,而不是和1或者0比较:

if(b){}  //判断是否为真
if(!b){} //判断是否为假

3、三目运算符(?:)

C语言中三目运算符表达式返回的是值,不是变量,所以不能作为左值来使用。

比如(a>b?a=100:b=100);只能写成*(a>b?&a:&b) = 100;。

C++中三目运算符表达式可以作为左值使用,因为表达式返回的是变量。上式可以写成(a>b?a:b) = 100;。

其实在C++编译器内部,是将式子转换为类似*(a>b?&a:&b) = 100;的形式来执行的,因此,三目运算符如果要作为左值使用,返回值的表达式中必须没有常量,因为常量没办法取地址,如这种写法就是错误的:(a>b?a:10) = 100;。


4、const关键字

C语言中,const修饰变量,变为只读变量,本质上还是一个变量,不是常量。

C++中,const修饰变量后,变量就变成了常量,所以可以用const去定义常量。

C++中常量是放在一个常量表中(不会在定义时,像变量一样开辟一个空间),常量表由编译器维护。

常量是没有办法取地址的,但是在C++中,对常量取地址并不会出错,如下面这个情况:

const int a = 100;
int *p = (int *)&a;
printf ("*p = %d,p = %p\na = %d,&a = %p\n",*p,p,a,&a);


这是为什么呢?原来,当编译器检测到要对const常量进行取地址操作时,它会为此常量分配内存,但是这个内存不会被该常量使用,而是被指向此块内存的指针使用。涉及到此常量名的地方还是用常量表中的值替换。如下:

const int a = 100;
int *p = (int *)&a;
printf ("*p = %d,p = %p\na = %d,&a = %p\n",*p,p,a,&a);

*p = 20;
int b = a;
printf ("*p = %d,a = %d,b = %d\n",*p,a,b);


其实,C++中的const常量就是为了取代宏常量的。

define宏在预编译阶段处理,这样编译阶段就看不到此符号,产生错误也不会报该符号的错,而是替换的值的错,不利于调试时寻找错误。而const常量会在编译阶段处理。

宏只做简单替换,不会进行类型检查和作用域的检查,宏的作用域从定义位置到文件结束都可以使用,除非用#undef撤销。而const常量会进行类型检查和作用域的检查,作用域在当前的大括号内。

宏可能会开辟多次空间,有多个备份,而const常量只定义一次。

5、inline关键字

说到宏,那就要提到宏函数,宏函数是一种完全替换,在于编译阶段处理,可以避免调用函数时的出入栈、跳转和返回的开销(此开销并不大)。不过宏函数没有函数参数、返回值、作用域的检测,而且形式上也与一般函数不相同,使用时会比较麻烦。比如定义时需要这样:

#define MAX(a,b) ((a)>(b)?(a):(b))

如果少了这些括号,在某些情况下(比如参数是个表达式或者连在一起调用)就会达不到我们预期的效果,如下(预期结果是400):

#define MAX(a,b) a>b?a:b
int a = 10;
int b = 20;
printf ("max*max = %d\n",MAX(a,b)*MAX(a,b));


当然定义正确了,有时也会出问题(预期结果是21):

#define MAX(a,b) ((a)>(b)?(a):(b))
int a = 10;
int b = 20;
printf ("max*max = %d\n",MAX(++a,++b));


C++中提供了内联函数来替换宏函数(工作方式与宏函数类似,是一种非完全替换的函数体替换)。普通函数之前加关键字inline可以变成内联函数。需要注意的是inline必须在函数定义的时候修饰,和函数声明放一起是被忽略的。如下:

inline int func(int a,int b)
{
	return a+b+a+b;
}

int main()
{
	int a = 10;
	int b = 20;
	printf("a+b+a+b = %d\n",func(++a,++b));
	return 0;
}


内联函数在编译阶段处理,会进行函数参数、返回值、作用域的检测(和函数非常像)。inline修饰后,会向编译器请求在调用该函数时进行函数体的替换,编译器可能会拒绝请求,这时就作为普通函数。如果内联成功,编译成功后,代码是没有这一段函数的原代码的。

想要内联成功,就要注意以下点:

函数体不要过长,最好不要超过5行;函数体不能有循环语句和复杂的if语句。(其实这也适用于宏函数,不然占空间太大,反而有反效果,毕竟函数调用的开销并不大)。

由于内联函数是做一个替换,所以没有函数入口,也不能对内联函数进行取地址操作。内联函数也存在常量表中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值