C++四大准则理解

一、最高准则:无二义

对该准则的理解

该准则其实不难理解,即任何语句的定义是足够精确的.也就是说,我们在编程的时候需要把自己的思维转换成无二义的表达,不能让计算机误解我们的意思.

其实以数学举例,数学发展过程中一个非常重要的标志便是数学定理的公理化,在很大程度上和计算机语言的无二义是有很多相似之处的,在牛顿时代,虽然微积分的工具被发明出来了,但是有非常多的标准未被确立,例如什么才是极限的一个定义.而数学被公理化的一个重要的标志就是柯西所提出的极限的定义,连续型的定义,例如 ξ − N \xi-N ξN语言等.

具体体现

(1)函数中的参数传递问题

在定义函数时,默认参数的设置的时候我们必须把默认参数的设置放到最后:

void func(int a, int b, int c = 1, int d = 1)
{
	return 0;
}

如果我们将默认参数放到开头或中间则会出现具有二义性的问题:

void func(int c = 1, int d = 1, int a, int b)
{
	return 0;
}

当我们使用如下代码:

func(1, 2, 4);

计算机并不能确定我们到底是将参数传递给哪一个形参.所以Cpp中直接规定默认参数放在最后.

(2)悬垂问题

当一个if语句嵌套在另一个if语句内部时,很可能if分支会多于else分支。这时候问题出现了:我们怎么知道某个给定的else是和哪个if匹配?

而对C++而言,它规定else与离它最近的尚未匹配的if匹配,从而消除了程序的二义性.同时,可以使用花括号来保障if-else的控制语句不出错.例如:

if (grade % 10 > 3)
	if( grade % 10 > 7)
		lettergrade += '+';
else
	lettergrade +=  '-';

从代码的缩进格式来看,程序的初衷应该是希望else和外层的if匹配,也就是说,我们希望当grade的末位小于3时执行else分支。然而,不管我们是什么意图,也不管程序如何缩进,这里的else分支其实是内层if语句的一部分。此时可以引入花括号达到我们的目的:

if (grade % 10 > 3){
	if( grade % 10 > 7)
		lettergrade += '+';
}else
	lettergrade +=  '-';

(3)运算符优先级问题

在运算中,加减法的优先级低于乘除的优先级.优先级会影响程序的正确性,所以有时候需要使用括号等形式对其进行相关的处理.举一个指针的例子:

int ia[] = {0, 2, 4, 6, 8};
int last = *(ia+4); //此时代表将last初始化为8
last = *ia+4; //此时是将last赋值为ia[0]+4

从该例子可以看出,运算过程也是体现了程序语言无二义的定义的.其他的例子还要i++和++i等语句也是体现了程序无二义的.

(4)贪心法则

贪心法则是编译器处理符号的一种方式:
1)编译器处理的每个符号应尽可能多的包含字符
2)编译器以从左向右的顺序一个一个尽可能多的读入符号
3)当读入的字符不可能和已经读入的字符组成合法字符为止.

例如:a+++b用括号表示为(a++)+b

(5)变量名不能以数字开头

主要原因是计算机很难辨别以数字开头的变量到底是属于常量或者变量

二、次高准则:高效性

对该准则的理解

C++语言将高效性作为次高准则,是因为C++语言出现时,计算机性能普遍较低,因此计算机性能是一个重要的制约因素,是当时情境下的“主要矛盾”

如果有两个行为A与B,均满足无二义的规则,且A比B高效,则C++语言会选择A行为作为标准语法。如数组下标选择0索引而非1索引。

需要说明,并非所有语言,都有对高效性的绝对准求。高效性准则只对基础的C++语法规则有效,在STL库与模板中,已经不再是次高准则了。

具体体现

(1)数组下标

数组下标在Cpp中是以0为起始的,主要原因是以0为起始点比以1为起始点效率更高;主要是因为计算机的索引是从下标为0开始的.如果在下标0索引的情况下,计算机可以减少一次减法运算,考虑到计算机减法是通过计算机的补码来实现,通过下标0索引可以提高计算机的高效性,因此才用了与人日常习惯相反的规则.所以Cpp的语法选择了以1为起始点.而现在对数组下标使用始终为进行修改主要还是一种因循随俗.

而其他语言,例如R语言,则是以下标1为数组,列表等结构的起始点.

(2)内联函数

执行到函数调用指令时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈(为此保留的内存块),跳到 标记函数起点的内存单元,执行函数代码(也许还需将返回值放入到寄存器中),然后跳回到地址被保存的指令处(这与阅读文章时停下来看脚注,并在阅读完脚注后返回到以前阅读的地方类似).来回跳跃并记录跳跃位置意味着以前使用函数时,需要一定的开销,

C++内联函数提供了另一种选择.内联函数的编译代码与其他程序代码“内联”起来了.也就是说,编译器将使用相应的函数代码替换函数调用.对于内联代码,程序无需跳到另一个位置处执行代码,再跳回来.因此,内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存.内联函数可以被如下定义:inline void func().

三、第三准则:合乎日常习惯

对该准则的理解

程序设计语言最终是给程序员使用的.一套不合乎日常习惯的规则,会给程序员的使用带来极大的不便性,因为日常习惯的惯性是极其强大的.这样会迫使程序员放弃该语言.所以这就要求语言尽可能的符合人类的惯性的思维,以减少在编程过程中出现语法的错误.

具体体现

(1)运算优先级问题

和前述问题相同:运算优先级的确定不仅保证了无二义性,同时也是对合乎日常习惯准则的体现.因为在日常生活中,程序员已经适应了相关的语法规则.

(2)相关内置函数的命名

在Cpp中不少内置函数是符合我们人类的命名规则的.以下为输入流和输出流的简介:

cin(发音为see-in)的istream类型的对象。这个对象也被称为标准输入(standard input)。对于输出,我们使用一个名为cout(发音为see-out)的ostream类型的对象。此对象也被称为标准输出(standard output)。标准库还定义了其他两个ostream对象,名为cerr和clog(发音分别为see-err和see-log)。我们通常用cerr来输出警告和错误消息,因此它也被称为标准错误(standard error)。而clog用来输出程序运行时的一般性信息。

通过此我们不难理解,我们读取数据时需要使用cin语句,同时使用cout向窗口输出信息.

(3)*与&

指针是指向另一种类型的符合类型.我们可以利用指针来对对象进行访问.例如以下代码:

int ival = 42;
int *p = &ival;  //此时指针p就会指向该对象

同时,一个比较生动形象的例子来源于课堂上所将的swap函数的例子,该例子很好地反映了指针的特性,即指针是指向一个对象的,我们可以通过直接对函数形参进行赋值,改变其指向对象的值.如下代码所示:

void swap1(int *x, int *y)
{
	int t = *x;
	*x = *y;
	*y = t;
}
int main()
{
	int x = 1;
	int y = 2;
	cout << "before:" << x << ends << y << endl;
	swap1(&x, &y);
	cout << "after:" << ends << x << ends << y << endl;
	return 0;
}

同时另一个针对指针比较生动形象的例子来源于前述的一个例子:

int ia[] = {0, 2, 4, 6, 8};
int last = *(ia+4); //此时代表将last初始化为8
last = *ia+4; //此时是将last赋值为ia[0]+4

第二行代码中,针对*(ia+4)最后得到的结果为该数组的最后一个值可以看出指针的特性.

四、补充准则:相似相同原则

对该准则的理解

C++中,如果有两个不同的对象A与B,A有行为a,B有行为b,如果a与b两种行为在逻辑上具有相似性,则C++会为对象A额外增加一个行为b,也会将对象B额外增加一个行为a。

这个准则比较好理解,其实也就是说在对一个变量或者对象进行操作的时候,当对A类型的对象增加了一个新的操作时,对B类型一般而言也会增加一个操作,其实也就是提供给我们更多的方式去记忆和理解Cpp的方式.

具体体现

(1)声明与赋值

①在定义变量时的赋值符号一般是=,例如针对变量a进行赋值有int a = 1;而针对对象的赋值方式对变量的赋值同样有效int a(1);同样针对列表也有列表初始化语句,int a{1};

②对于指针的初始化与赋值也是有相似的规则,以下代码可以对应指针与变量的初始化过程:

int *p=&a;
int *p(&a);
int *q=p;
int *q(p);
int *q{p};
int *q = {p};

五、总结

以上为目前在Cpp中所遇到的对于四大准则的一个总结,目前自己的编程经验较为欠缺,所以特别是对于相似相同规则的了解的不足.不过相信理解这些规则在一定层面上能够较高效率的使自己在编程中少犯错,同时对其理解的深刻对于将来学习其他编程语言,强化自己的能力有较大的帮助.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值