下面几种风格都是可能的:

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类型的普通变量。为了避免产生这种混淆,我们尽量不在同一个语句中声明多个实体。