C++ Primer 阅读笔记–const、模板和重载
准备面试C++岗,把这本书翻出来查漏补缺一下。
const变量和const指针
之前学c的时候,觉得const貌似没啥用,只会增加很多限制。后来写了CUDA发现,const有时候是可以在编译期发现一些错误,还是很有用的。这次看了C++ primer plus,在const指针上发现自己不熟悉的一点,特此记下来。
const int *a
,表示该指针指向的数据无法通过*a=3这种语法来修改,但是a的指向是可变的;
int* const a
,表示该指针的指向是不可变的;
如果想兼顾两者,可以这么写:const int* const a;
在赋值时,允许将变量的地址赋值给const指针,但是不允许将const变量的地址赋给非const的指针。原因是这样做会导致const变量的值通过非const的指针被修改,其const属性就失去意义了。
对于超过两层的指针,不允许常量/变量间的指针混用,即如下的赋值不被编译器允许:
const int **pp2;
int *p1;
const int n=13;
pp2=&p1; //in fact, not allowed
*pp2=&n;
*p1=10;
可以看到上述代码中,由于对二级指针的不恰当的赋值,n的值被修改了。
函数的参数尽可能使用const的理由有二:
- 避免无意间修改不应该修改的数据导致出错。例如,对于一个统计数组内整数之和的函数,其传入的参数应该定义为const,防止函数无意间修改了传入的数组导致错误。
- 使得函数可以处理const的数据。如果参数不用const标识,则只有非const的数据可以作为参数传入。
- 对于引用作为参数来讲,使用const可以使非左值的量也可以作为引用的参数传入
二维数组作为函数参数
int sum(int(*ar)[4], int size); // int sum(int ar[][4], int size) is also ok
int data[3][4]={{1,2,3,4},{3,4,5,6},{4,5,6,7}};
sum(data, 3);
需要说明的是,int(*ar)[4]
加括号的原因是,int* ar[4]
的含义是4个int指针的数组。
函数重载(C8)
函数重载时,有些小细节需要注意。
- 重载的函数特征仅限于参数表
- 类型引用和类型本身对于参数会被视为同一个特征标
函数模板(C8)
C++的模板给我们对不同的变量类型统一写函数的机会。基本的语法详见书籍,这里只说一些需要注意的点。
具体化和实例化
模板具体化:对于某种类型定义了一个函数,以后调用这个函数不使用模板生成实例函数,直接用这个具体化的函数进行调用。
模板实例化:仅仅是对模板的某种类型进行了实例化,调用函数时依然要找模板。只是因为这里这个类型对应的函数被实例化过了,所以直接找到这个实例化过的函数。
函数重载解析(C8)
重载解析主要步骤
- 创建候选参数列表。
- 在候选参数列表中寻找可行参数。(参数数目正确、可转换)
- 在可行参数列表中寻找最佳参数。
最佳参数选择匹配顺序
- 完全匹配:常规函数>模板,如果两个函数都是模板函数,则最具体的模板函数优先。(例如,如果传入的变量是个指针,则指针模板比基本类型模板优先)
- 提升转换:float->double,shorts->int…
- 标准转换:int->char,long->double…
用户定义的转换
编译器只会选择一种最佳的匹配。如果存在多个最佳匹配,编译器会报二义性错误。