C++中逗号分隔多变量声明的规则咨询(需标准引用)
你提到的几种声明场景,核心区别在于修饰符的归属范围——C++的声明语法把修饰符分为三类,作用规则完全不同:
1. 存储类说明符(static/extern等):作用于所有标识符
像static int a, b;这类声明里,static是存储类说明符,它不属于类型的一部分,而是给整个声明里的所有标识符加上存储属性。所以a和b都是static int类型。
根据C++20标准[basic.stc]的规定:
存储类说明符适用于声明中的所有实体。当声明包含多个声明符时,存储类说明符会应用于每个声明符所指代的对象或函数。
2. 类型限定符(const/volatile等):修饰基础类型,作用于所有匹配的声明符
const int c, d;里的const是类型限定符,属于基础类型int的一部分,所以整个声明的基础类型是const int,c和d自然都是const int。
但如果声明符带指针/引用修饰符,情况会变:比如const int* p, k;,这里类型说明符是const int,声明符*p表示“*p的类型是const int”,所以p是指向const int的指针;而声明符k直接对应基础类型,所以k是const int。
对应C++20标准[dcl.type.cv]的内容:
类型限定符可以应用于对象类型。当出现在类型说明符序列中时,它限定该声明中所有声明符所指代对象的基础类型,除非声明符本身的修饰符改变了类型结构。
3. 复合类型修饰符(*/&/[]等):仅作用于紧跟的标识符
这就是你提到的int* p, k;的情况:*是指针修饰符,属于单个声明符的一部分,只绑定后面的p。所以p是int*,而k没有这个修饰符,就是普通的int。
类似的,int& x, y;里x是int&(引用),y是int;int arr[5], num;里arr是数组,num是普通int。
根据C++20标准[dcl.decl]的定义:
声明符由可选的修饰符(如指针、引用、数组标记等)和标识符组成。每个声明符独立定义其指代实体的类型,类型说明符序列提供基础类型。
一句话总结
- 写在类型前面/和类型绑定的修饰符(
static/const):影响所有标识符(除非声明符有复合修饰符) - 写在标识符前面的修饰符(
*/&):只影响当前标识符
内容的提问来源于stack exchange,提问作者user8393252

