2013年一月份在别的地方写的博客,现在搬过来。回头看看,那时候的文风还真是有趣呢~


《C++ Primer》这本书带看不看的好多年了。每过一段时间,就拿出来看看。书都折胶了。常看的章节也都泛黄了。但是很多细小但是很重要的点仍然记不住。总是翻看时记得很清楚,但是过一段时间就模糊了。以前总是想把这本厚得跟转头一样的书的要点整理出来,弄成一个很薄很薄的内容。这样每过一段时间就翻出来看看,容易复习。

最近想,为何不整理在微博里呢?这样共享出来,还能给朋友们一起看看。当然,看这些内容的人,我希望你还是要有点相关知识的基础的。因为我不会从零开始。如果没看过《C++ Primer》,就得自己先看看了。

好吧,第一次废话比较多。今天咱们就聊一聊关键字const

const,大家都知道,表示这个量是个常量,不能变化。也就是说,凡是用它修饰的东西,必须在声明的时候给它初始化,不然这个东西(就是常量)就再也没有被改变的机会了。比如:

const int MAXNUM = 100;

这就表明,MAXNUM在它活在世上这一辈子里(就是生命周期中),就只能是100了。从生到死,始终表里如一,平静如水,毫无变化。

这很简单吧?原本一切都是这么简单,这么美好。但是当const遇到别的东西的时候,一切都开始复杂了,开始让人捉摸不定,让人困惑。就好比人生,自己一个人总是很简单,当你开始恋爱了,有家庭了,有孩子了,一切都变了。就连生活习惯都可能改变了!

一、当简单明了的const遇到万恶的指针,注定会产生峰回路转、曲折离奇的爱情故事

指针,万恶之源。产品里很多的bug,都是来源于指针。什么指针没释放,导致内存溢出啊;什么指针还需要使用,指向的内存空间就被释放了啊。有人说C++和C难学难用的原因之一,就是因为要自己管理指针。这话有点道理。

那么如果const爱上指针,会产生什么呢?可能大家张嘴就能说,当然是“const类型的指针”和“指向const类型的指针”啦!

不过,可能令你很惊讶的是:const和指针之间的体位却有三种!看下面的code:

int a = 1;
int b = 2;
int c = 3;
int d = 4;

int const* p1 = &a;
const int* p2 = &b;
int* const p3 = &c;

你可能会想:为什么会有三种呢?亲!不是只有两种结果吗?这不是真的,p1p2p3当中一定有一个是错误的结合!

我告诉你,这三种都是他们合法的爱情的结晶。另外,谁告诉你,相同的结果只能有一种表达方式了?比如无论 是西红柿炒鸡蛋,还是鸡蛋炒西红柿,还是番茄鸡蛋,这都是一样一样一样的啊!亲!

p1p2其实是一样的!都是指向const类型的指针,也就是说,不能通过p1p2,来分别改变ab的值。不过,庆幸的是,p1p2在指向一个对象以后,不一定非得一棵树上吊死,它俩还可以指向别的对象。就好像,如果你结婚后对方不能带给你幸福,而自己又无法改变对方。那么,看完这个类型的指针,你就知道了,都什么年代了!你可以离婚去追求自己的幸福啊,亲!

p3const类型的指针。它一旦指向某一个对象,那么这辈子就只能指向它了。正所谓嫁鸡随鸡,嫁狗随狗。忠贞不二!这是中国男人心目中的好老婆。当然,p3也是好指针。当你和一个老外交谈,说到一个比较好的观点时,对方往往会说,good point!什么意思呢?就是good pointer的口语简化,就是“好指针”的意思!

不过,p3如果看对方不爽,可以改变它!此时,我的脑海里浮现出很多别人老婆的光辉形象,比如俞敏洪的老婆啊,李彦宏的老婆啊。这些老婆们,都是good point!

正所谓龙生九子,各有不同。p1p2p3这哥仨,经过const和指针的杂交,在外形和功能上至少有一方面不同,那么我们到底怎么区分呢?

const想成老婆,把int(或者别的变量类型)想成第三者,那么老婆和你站在同一边的,也就是都在* 号右边的,远离第三者的,就是同甘共苦,荣辱与共,也就是我们所说的好老婆,就是const类型的指针;而老婆和你在* 号两边的,离第三者总比离你近的呢?就是属于同床异梦的,就是指向const类型的指针。正所谓夫妻本是同林鸟,大难临头各自飞。p1p2的日子不好过啊。

如果我说这么形象你还记不住,那么……记得常喝六个核桃!

二、三个孩子还有故事

简单说说这仨倒霉孩子。

1.孩子们的指向到底有没有问题?

指向const类型的指针,也就是p1p2,一般是用来指向const类型的对象的。这本无可厚非。但是,他们可不可以指向非const类型的对象呢?

答案是:可以滴!

不过,我们仍然不能通过这类指针去改变他们所指向的对象的值。为什么呢?原因就是p1和p2这哥俩天生就有缺陷。只要让他们指向了,看谁都是const类型的对象!可悲吗?

所以夫妻生活一定要幸福,不然生下来的小孩都不健康哦~

那么,大家很快会想到p3了。const类型的指针呢?const类型的指针可以指向非const类型的对象,但是它坚决不会去指向const类型的对象。因为,它知道,它是要改变对方的,如果对方不向它敞开心扉,它干脆放弃。

顺便说一句,void*指针不能用来指向const类型对象,必须用const void*

2.偶尔有别的东西出来客串,再脑残也是要交朋友的!

再来看看这个code:

typedef int *intPoint;
const intPoint p5;

那么p5到底是“const类型的指针”还是“指向const类型的指针”?

大家一定会说p5是“指向const类型的指针”。嗯,但是错了!哈哈!其实人家p5是“const类型的指针”呢~

为什么呢?估计大家是内联的展开了intPoint。其实也没错。但是不管怎样,intPoint始终是个指针,那么const修饰指针,那当然是“const类型的指针”啦!

三、还有一个私生子,嘘~能不说就不说吧!

看下面的code:

int d = 4;
const int* const p4 = &d;

这种指针很少露面。一般都隐匿起来。为什么呢?因为这个是“指向const类型的const指针”。这类指针,一旦初始化之后,既不能通过它改变指向类型的值,也不能指向别的指针。所以基本上就是个废物,出场率不高。

想想吧,同时娶两个老婆(const),在新中国已经不允许了!虽然很多男人都想这样……

四、当const为函数打工,小秘和老板之间总有无限引人遐想的故事

一个类里的成员函数,它不想改变类里的任何成员变量。但是它自己没有这个自制力,所以想找人来管管。于是乎,它找到了const。看这一段code,这是一个定义在类Sales_item外面的成员函数,摘自《C++ Primer》第四版:

double Sales_item::avg_price() const 
{ if (units_sold) 
     return revenue/units_sold; 
  else 
     return 0; 
 } 

avg_price()没有改变任何的成员变量,事实上,它想改也改不了。一切都在const的严格控制当中。const的限定非常严格,我猜它是处女座的!

当然,我们只有const成员函数。如果不在类里,就没有const函数。你可以把在类里的函数想象成在体制内的部门。这种部门总是约束这约束那,所以得有const。但是体制外的,社会闲杂人等,不需要什么约束。

五、结束语

说了这么多,有可能有遗漏的。毕竟关于const,总是有说不完的话题。但是基本万变不离其中吧。运用基本知识,解决复杂问题。如果以后真有什么我觉得可以补充的,再开博客再详谈吧。

真佩服那些有毅力的人,能从头看到这里。

本文固定链接: http://www.js-code.com/cpp/cpp_58855.html