早就想介绍一篇关于华为经典面试题的文章,不过想了好几次都觉得还是太早了,很多基础的知识我们还没有介绍。那样的话就算说了,大家特别是初学者们都云里雾里。我们今天介绍的这个关于等号的故事就是其基础知识的一部分。大家一定要仔细看。
在这之前我们先来介绍一个曾经非常经典的故事:比较两个数据是否相等要怎样做?在不同的时期和环境下,答案是不同的。以笔者在学校中最早教授的pascal来说,那么代码很简单:
if变量1=变量1then做各种事情
在学习了C语言之后这个问题让我们第一次接触到C语言变态的一面,或者说是与常人逻辑相违背的一面--这是我们在学习C/C++语言整个过程中都一直要克服的问题和心理障碍。当然了学过C语言的同学都知道,用一个等号完成这个任务是不行的,要用两个等号...当然了这不只是C语言的问题,在学习pascal的时候我也花了很长的时间云了解:=与=为什么要写成不同的,为什么不能用同一个?不知道大家的老师是怎么解释的,我们的那位白发苍苍的老教授是这样说的:因为它们一个是比较,一个是赋值。说实话我是真的没听懂。要觉得要以我现在的理解感觉这样解释更合适,它们一个表示两个操作数是否相等;一个表示将数据复制给对方,虽然在中文里面它们都可以表达为“等于”。也不知道,在校的同学们能理解我说的不。当然了这个并不是什么大问题,只要大家系统学习过编程就是能理解的。不过关于这个区别会引发一个C语言里非常经典的问题:那就是很容易在使用==号的地方误用为=,在我们的那个年代据说这曾经导致某次火箭发射的失败。这主要的原因是因为两个操作符号实在是太相近了。这个问题引发了一个同样非常经典的语法的改变,那就是人主张通过把常量写在前面来避免这个问题,比如如果写成:
if(1=变量1){做各种事情}
那么就无法编译,从而避免了这一经典的错误。应该说这是一个好办法,我也经常用。不过在现在类横行天下的时代很多时候意义没那么大。比如运算符号左右都是类的情况怎么办?在java里还会特别说明用=号是无法比较两个字符串是否相等的。这让在多个语言中切换的程序员非常崩溃,要知道在这之前等号运算符一直是用来比较的,现在告诉我们不行...这里深层次的原因是java里的字符串都是引用,用C++的角度来理解的话那就是说两个比较只是比较了它们的指针不同,如果不同的两个地址中的字符串内容实际上是一样的话那就会复出错误的答案。好吧,那我们记住新的以类为主的语言等号不能比较内容吧!......这样平静了几年后时代又发生了可怕的变化:C#允许使用==来比较两个字符串!你会说微软这个变态,不用理它......等等,现在新出来的google公司的go语言也有用==来比较两个字符串!也不知道从什么时候开始,开发语言已经刻意的采取措施来解决等于符号给人造成的错觉了。其实我个人来说这几种做法各有利弊吧,像我这种经常要在多个语言里切换的可怜虫来说,我已经很长时候不敢使用这个操作符号比较字符串了,我都是用的的比较函数,比如什么equals啦,什么Compair啦,反正各个语言里都有,那个符号你们折腾去吧...我总觉得这样下去迟早有一天会有人倡导废除这个比较操作符号...当然了,我们这篇文章不只是调侃一下各个语言。我真正想说的是:就让我们来做那个废除这个操作符号的人吧,我要让=和==在折腾字符串的时候都是复制内容而不是比较是否相等,为了实现这个目标我已经学习了编译器技术,对C++的改革就要开始了......大家一定觉得我疯了,不过我要说的是,另写一个编译器来实现这个目标是有点疯,不过要实现这个目标并不疯。啥意思,大家已经被绕晕了。我的意思是说,我们现在就能让C++字符串的==比较功能废掉。
先让我们来看看这段代码:
字符串类的实现这其实是字符串类非常常见的一些实现函数,当然,对大多数初学者来说,恐怕没几个看得懂的。这是因为这些代码比较特殊一般的学校实在也没有必要教。我自己当年也没有重视,因为C++语言的特性实在是太多了,每种都深入研究的话一两辈子是不够的...不过这个特性确实应该掌握,这就是所谓的运算符重载了。具体的语法大家可以自己再百度。简单来说,运算符重载可以让我们自己控制=和==当然也包括+、-这些运算符号操作的结果是什么,用在我们前面说的字符串比较来说就是想让它是复制内容就是复制内容,想让它是比较是否相等就是比较是否相等,完全由我们做主。上面的代码是重载=符号的,其实==也类似,如下:
等于符号完全自己做主这个语法的主要用途就我个人从业生涯看到的来说,主要就应用在字符串类的实现上。但是借助它我们可以让C/C++更安全。
好了,希望大家掌握这个语法,我们在后面的文章中还会要用到的。