在日常交流中,当一个 C++ 程序员说“常量指针(const pointer)”时,其实他表达的意思往往是“指向常量的指针(pointer to const)”。真不幸,这是两个完全不同的概念。
T *pt = new T; //一个指向T的指针
const T *pct = pt; //一个指向const T的指针
T *const cpt = pt; // 一个const指针,指向T将const 修饰符放到指针声明之前,应该想好,到底想叫什么东西变成常量, 是指针?还是准备指向的那个对象?或兼而有之?
在 pct 的声明之中,指针不是 const 的,但它所指向的对象被认为是 const 的。换句话说,const 修饰符修饰的是基础类型 T 而不是指针修饰符 *。而对于 cpt 的声明来说,声明的是一个指向一个非常量对象的常量指针,即 const 修饰符修饰的是指针修饰符 *而不是基础类型 T。
声明中修饰符(即指针声明中第一个 * 修饰符之前出现的任何东西)的顺序无关性进一步混淆了围绕指针和常量的语法问题。例如,以下两行代码所声明的变量的类型完全相同:
const T *p1;//一个指向常量T的指针
T const *p2;//也是一个指向常量T的指针
第一种形式更传统一些,但如今许多 C++ 专家推荐使用第二种形式。理由在于,第二种形式不太容易被误解,因为这种声明可以倒过来读,即“指向常量T的指针”。使用哪一种形式无关紧要,只要保持一致就行了。然而务必小心一个常见的错误,即将常量指针的声明与指向常量的指针的声明混淆。
T const *p3;//一个指向常量的指针
T *const p4;//一个常量指针,指向非常量T
当然,可以声明一个指向常量的常量指针:
const T *const cpct1 = pt;//二者均为常量
T const *const cpct2 =cpct1;//同上