在C++指针常量和常量指针的学习中,我们经常会碰见这样的例子:
A. const char *pContent;
B. char * const pContent;
C. char const *pContent;
为了便于理解,很多教材是这么加括号的:
A. const (char) *pContent;
B. (char*) const pContent;
C. (char) const *pContent;
也许这样对理解指针常量和常量指针的用法会有一定的帮助,但严谨的来说,将 char 与 * 放在一起是错误的,因为两者的性质根本不同。在C++中,实例(Object)的声明其实包含两部分:Specifier 和 Declarator,在上面的例子中,char 属于 Specifier,而 * 则属于Declarator,const 则根据其位置的不同处于不同成分。
在《Cpp in a Nutshell》一书中,有如下的说明:
Specifier:contain a storage class, const and volatile qualifiers, and the object's type, in any order.
例子:extern const long int objectname;
其中 extern 属于存储类型(storage class),const 属于 cv-qualifiers,long int 属于变量类型。它们的顺序任意,也就是说上面的例子等价于:int const extern long objectname;
Declarator:contains the name being declared, additional type information (for pointers, references, and arrays), and an optional initializer
例子:int plain_int, array_of_int[42], *pointer_to_int;
其中整个句子是一个实例声明,而前面的 int 是 specifier,它的内容同时作用于后面跟着的三个 declarator,分别是 “plain_int" (只有标识符),”array_of_int[42]“(标识符和数组修饰),”*pointer_to_int“(指针修饰和标识符)。另外初始化的部分也属于 declarator,specifier 和 declarator 一起组成了实例声明,如:int a = 1, b = 2, c = 3;
好了,回到指针常量和常量指针的例子:char * const pContent;
这是一个实例声明,所以包含了specifier和declarator两部分,两者以 *(&,标识符)为界,分为两部分:
Specifiers: char
Declarators: * const pContent
所以,这是一个指向char类型数据的常量指针。同理:
A. const char *pContent;
Specifiers: const char
Declarators: *pContent
C. char const *pContent;
Specifiers: char const
Declarators: *pContent
又或者:
const char * const pContent;
Specifiers: const char
Declarators: * const pContent
简单的说, *(&,标识符)及其以后的部分都属于 declarators,只要抓住了这一点,无论是多复杂的指针常量和常量指针都能够很容易地区分开来。