最近一直在复习C++的语法,感觉遇到了不少问题,或许是之前没想的这么深。废话不说,开始说正事。
一、再谈const
有些朋友可能有些疑问,不就是const吗?我知道,const可以给非const赋值,反过来不行,但是真的仅仅只是这么简单嘛?绝对不是,如果这么简单,那么我们在写代码的时候就不会出现const不可转换其他类型的错误了。希望大家可以认真看完,绝对是可以学到一些知识。(大佬除外)
看看下面的这道题,如下:
1,2,3这三个到底哪个是对的,还是那个是错误的,或是全对,亦或是全错?其实这里牵扯到了很多基础的知识,我个人认为是那种平常老师所说的基本功问题。
首先,不用判断的是,1绝对是对的。这个不知道大家有没有疑惑,其实很简单,就是定义了一个指针,修饰指针指向的内容是不可改的,但是指针本身可改。K函数的参数也就是形参是指针引用,也就是引用了ca。这个为什么是对的呢?很简单,就是我实参不可修改的*ca,所以形参在接受的时候,首先形参的*p是不可修改的,所以形参的const必须加在类型前,也就是A前,其次就很好理解了,那就是引用,直接引用即可。第一个还是很好理解的。
第二个,很明显错了,有些朋友可能懵了,what?实参是最大的权限,可修改任何地方(此处指可修改**p,*p,p),而形参只有不可修改**p,为什么是错的呢?很明显的正确啊,但是错了兄弟,格局小了,有些人很疑惑,为什么啊,为什么,这里形参的**p对是实参的**p是没有威胁的,因为按照权限来说,这里是把实参的权限给变小了,权限是可变小,可平移,不可放大的,但是这里是缩小,为什么还不对呢?其实很简单,这里就是我说格局小的原因,因为形参的**p是不可修改的,但是*p会啊,他会修改啊,有些朋友可能明白了,对没错,因为存在*p可修改的原因,导致他可能会把一级指针的内容修改了,也就是把一级指针的内容改成其他地址,所以这是一个潜在风险,所以不可以,所以2错误。理解了2,那么3相信大家应该是可以理解了吧,3明显是对的。这里就不再说了。
那么,三级指针呢??如下:
int a = 10;
int* p = &a;
int** pp = &p;
int*** ppp = &pp;
const int* const * ptr = pp;
const int*const*const * pppp = ppp;
正确的是上面这样写的。原理其实很简单,我感觉我其实没必要去背多余的八股文这些,什么时候加const,很简单,那就是没有威胁,什么是没有威胁??那就是不会对你指向的值产生威胁,也就是不会有潜在风险修改指向内容的值的时候,就合法的,如果有,那就要加const。引用其实也是同样的道理,这里就不再详细说明。所以,我们在想用不用const的时候,就看看有没有“威胁”。
二、模版参数
很多人可能说,模版没必要说,其实不然,不知道大家有没有这样写过代码,如下:
这是我昨晚复习STL时,写的代码,其实这个模版参数是错误的,但是,,,,,,有个方法直接可以把这个改对,是的,虽然模版参数不应该这样写,但是有一个方法可以修改,还是对的,还就是模版参数中。相信有些朋友猜到了,没错,就是typename。
typename不用多说,定义模版参数和说明是类型时用到的关键字。其实class 与 typename在定义模版参数的时候,是一样的,没有区别,这个是对的,但是我一直的疑惑就是这个,为什么我把class改成typename就对了,在模版参数中不是class 和typename一样吗,那他错在哪里了,为什么typename对,而class是错的,其实很简单,依赖类型。
模版参数类型有三种,类型参数,非类型参数,模版类型模版参数。
而其中有一种类型是依赖类型,什么鬼??什么是依赖类型,其实很简单,就是依赖模版类型的变量,假如模版参数中定义的T, 那么我们一般会用T来定义变量,那么此时这个变量就是依赖类型,因为他依赖了模版参数的类型。这种类型就必须要用typename来说明,所以很显然,如果我上面的那一块必须要这样写的话,那么就必须要用typename,而不能用class。(其实就是一个非类型参数)。这里想说的是模版参数中也要遵循这个规则,当编译器不知道是类型还是变量的时候都要用typename,类外,以上写法是错误的,就是想给大家说说,typename在模版参数的定义中也要注意变量还是类型,很重要。其实,定义模版时,建议用typename(虽然自己用的是class)。