问题描述
据我了解,C ++中的声明/初始化是带有基本类型"的语句,后跟逗号分隔的声明符列表.
From what I have understood, declarations/initializations in C++ are statements with 'base type' followed by a comma separated list of declarators.
请考虑以下声明:
int i = 0, *const p = &i; // Legal, the so-called base type is 'int'.
// i is an int while p is a const pointer to an int.
int j = 0, const c = 2; // Error: C++ requires a type specifier for all declarations.
// Intention was to declare j as an int and c an as const int.
int *const p1 = nullptr, i1 = 0; // p1 is a const pointer to an int while i1 is just an int.
int const j1 = 0, c1 = 2; // Both j1 and c1 are const int.
const int
是基本类型还是复合类型?
Is const int
a base type or a compound type?
从上面第二个声明中的错误来看,它似乎是基本类型.如果是这样,那么第一个声明呢?
From the error in the second declaration above, it seems to be a base type. If it is so, then what about the first declaration?
换句话说,如果第一个陈述是合法的,为什么第二个陈述不合法?另外,为什么第三和第四条语句的行为有所不同?
In other words, if the first statement is legal, why isn't the second one? Also, why does the behaviour differ among the third and fourth statements?
推荐答案
好问题,答案很复杂.要真正掌握这一点,您需要非常全面地了解C ++声明的内部结构.
Good question, with a complicated answer. To really grasp this, you need to understand the internal structure of C++ declarations quite thoroughly.
(请注意,在此答案中,我将完全省略属性的存在以防止过度复杂化).
(Note that in this answer, I will totally omit the existence of attributes to prevent overcomplication).
声明有两个组成部分:一系列声明符,后跟一个用逗号分隔的 init-declarators 列表.
A declaration has two components: a sequence of specifiers, followed by a comma-separated list of init-declarators.
说明符如下:
- 存储类说明符(例如
static
,extern
) - 功能说明符(例如
virtual
,inline
) -
friend
,typedef
,constexpr
- 类型说明符,其中包括:
- 简单类型说明符(例如
int
,short
) - cv限定词(
const
,volatile
) - 其他事物(例如
decltype
)
- storage class specifiers (e.g.
static
,extern
) - function specifiers (e.g.
virtual
,inline
) friend
,typedef
,constexpr
- type specifiers, which include:
- simple type specifiers (e.g.
int
,short
) - cv-qualifiers (
const
,volatile
) - other things (e.g.
decltype
)
声明的第二部分是逗号分隔的init声明符.每个init-declarator由一系列声明符组成,可选地,后面还有一个 initializer.
The second part of a declaration are the comma-separated init-declarators. Each init-declarator consists of a sequence of declarators, optionally followed by an initialiser.
什么是声明符?
- 标识符(例如
int i;
中的i
) - 类似指针的运算符(
*
,&
,&&
,指针到成员的语法) - 函数参数语法(例如
(int, char)
) - 数组语法(例如
[2][3]
) - cv限定符(如果它们遵循指针声明符).
- identifier (e.g. the
i
inint i;
) - pointer-like operators (
*
,&
,&&
, pointer-to-member syntax) - function parameter syntax (e.g.
(int, char)
) - array syntax (e.g.
[2][3]
) - cv-qualifiers, if these follow a pointer declarator.
请注意,声明的结构很严格:首先是声明符,然后是init声明符(每个声明符都可以有选择地后面是初始化符).
Notice that the declaration's structure is strict: first specifiers, then init-declarators (each being declarators optionally followed by an initialiser).
规则是:说明符适用于整个声明,而声明符仅适用于一个init-declarator(逗号分隔列表的一个元素).
The rule is: specifiers apply to the entire declaration, while declarators apply only to the one init-declarator (to the one element of the comma-separated list).
上面还请注意,cv限定符既可以用作说明符,也可以用作声明符.作为声明符,语法将其限制为只能在存在指针的情况下使用.
Also notice above that a cv-qualifier can be used as both a specifier and a declarator. As a declarator, the grammar restricts them to only be used in the presence of pointers.
因此,要处理您发布的四个声明:
So, to handle the four declarations you have posted:
int i = 0, *const p = &i;
说明符部分仅包含一个说明符:
int
.这就是所有声明符都将要应用的部分.The specifier part contains just one specifier:
int
. That is the part that all declarators will apply to.有两个init声明符:
i = 0
和* const p = &i
.There are two init-declarators:
i = 0
and* const p = &i
.第一个有一个声明符
i
和一个初始化程序= 0
.由于没有类型修改声明符,因此i
的类型由说明符给定,在这种情况下为int
.The first one has one declarator,
i
, and an initialiser= 0
. Since there is no type-modifying declarator, the type ofi
is given by the specifiers,int
in this case.第二个init声明符具有三个声明符:
*
,const
和p
.还有一个初始化程序= &i
.The second init-declarator has three declarators:
*
,const
, andp
. And an initialiser,= &i
.声明符
*
和const
修改基类型以表示指向基类型的常量指针".说明符给出的基本类型是int
,p
的类型将是指向int
的恒定指针".The declarators
*
andconst
modify the base type to mean "constant pointer to the base type." The base type, given by specifiers, isint
, to the type ofp
will be "constant pointer toint
."int j = 0, const c = 2;
同样,一个说明符:
int
,以及两个初始化声明符:j = 0
和const c = 2
.Again, one specifier:
int
, and two init-declarators:j = 0
andconst c = 2
.对于第二个init声明符,声明符为
const
和c
.正如我提到的那样,如果涉及到指针,则语法仅允许cv限定词作为声明符.这里不是这种情况,因此是错误.For the second init-declarator, the declarators are
const
andc
. As I mentioned, the grammar only allows cv-qualifiers as declarators if there is a pointer involved. That is not the case here, hence the error.int *const p1 = nullptr, i1 = 0;
一个说明符:
int
,两个初始化声明符:* const p1 = nullptr
和i1 = 0
.One specifier:
int
, two init-declarators:* const p1 = nullptr
andi1 = 0
.对于第一个init声明符,声明符为:
*
,const
和p1
.我们已经处理过这样的init声明符(在 1 情况下是第二个).它将指向基本类型的常量指针"添加到说明符定义的基本类型(仍为int
).For the first init-declarator, the declarators are:
*
,const
, andp1
. We already dealt with such an init-declarator (the second one in case 1). It adds the "constant pointer to base type" to the specifier-defined base type (which is stillint
).对于第二个init声明器
i1 = 0
来说,这是显而易见的.没有类型修改,请按原样使用说明符.因此i1
变为int
.For the second init-declarator
i1 = 0
, it's obvious. No type modifications, use the specifier(s) as-is. Soi1
becomes anint
.int const j1 = 0, c1 = 2;
在这里,我们与前三个情况截然不同.我们有两个说明符:
int
和const
.然后是两个init声明符,分别是j1 = 0
和c1 = 2
.Here, we have a fundamentally different situation from the preceding three. We have two specifiers:
int
andconst
. And then two init-declarators,j1 = 0
andc1 = 2
.这些init声明符中都没有任何可进行类型修改的声明符,因此它们都使用说明符中的类型,即
const int
.None of these init-declarators have any type-modifying declarators in them, so they both use the type from the specifiers, which is
const int
.这篇关于C ++中的声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- simple type specifiers (e.g.
- 简单类型说明符(例如