下面几种风格都是可能的:
void foo (const int &x); void foo (const int& x); void foo (int const &x); void foo (int const& x);
对“常整数”而言,上面的几种用法虽然差别不大,但我们趋向于使用int const,而不使用const int。作出这个选择,主要有两个原因:首先,针对问题“什么是恒定不变的?”,int const提供了很容易理解的答案。实际上,“恒定不变部分”指的是const限定符前面的部分。例如,尽管
const int N = 100;
等价于:
int const N = 100;
但是对于:
int* const bookmark; //指针不能改变,但指针指向的值可以改变
却没有相应的等价形式(就是说如果把const限定符放在运算符 * 的前面,与前者并不等价)。在这个例子中,我们只是说明了指针本身是个常量,而并没有说明这个int值(即指针指向的值)是个常量。
同理可推断
char const* p = "123"; p = "345";//可以 const char* p = "123"; p = "345";//可以 char* const p = "123"; p = "345";//不可以,但是修改123的内存可以
第2个原因涉及到使用模板时一个很常用的语法替换原则。考虑下面的两个类型定义 :
typedef char* CHARS; typedef CHARS const CPTR; //指向char类型的常量指针
当我们用CHARS所代表的含义对它进行替换之后,第2个声明的含义是不变的:
typedef char* const CPTR; //仍然是指向char类型的常量指针
然而,如果我们把const放在它所限定的类型的前面,那么这个原则就不再适用了。针对我们前面给出的两个类型声明,考虑下面的替换代码:
typedef char* CHARS; typedef const CHARS CPTR; //指向char类型的常量指针
但如果我们替换掉CHARS之后,第2个声明却会导致不同的含义:
typedef const char* CPTR; //指向常量char类型的指针
当然,同样的现象(规则)也适用于volatile限定符。
对于间隔符,我们决定在 & 符号和参数名称之间留出一个空格:
void foo (int const& x);
借助这种方法,我们同时也强调了:参数类型和参数名称是分离的。
显然,诸如下面的声明更容易令人混淆:
在C++中,类型定义只是定义了一个“类型别名”,而不是一个新的类型。例如:
typedef int Length; //定义Length 为int的别名 int i = 42; Length l = 88; i = l; //正确 l = i; //正确 char* a, b;
上面代码中,如果根据C语言的规则,a是一个指针,而b是一个char类型的普通变量。为了避免产生这种混淆,我们尽量不在同一个语句中声明多个实体。