4

Bjarne 解释了为什么 const 可以放在类型之前或之后。

http://www.stroustrup.com/bs_faq2.html#constplacement

"const T" and "T const" were - and are - (both) allowed and equivalent.
[...]

为什么?当我发明“const”(最初命名为“readonly”并有一个相应的“writeonly”)时,我允许它在类型之前或之后出现,因为我可以这样做而不会产生歧义。

我的直接想法是,“好吧,这是有道理的,但如果这就是原因,那么为什么 const 是特殊的?” 显然不是。clang 和 gcc 都不会发出以下警告。

int volatile myint;
int static myotherint;

这是有道理的,但我从未见过这种语法被使用过,甚至没有被提及过。是否在类型有效的 C++ 之后放置 static 和 volatile 限定符?

如何从标准的文本中确定这一点?

4

3 回答 3

4

是的,这种语法很好。声明语法的第一部分是一个decl-specifiers序列。这些包括存储类指定、类型说明符、函数指定、friendtypedefconstexpr。语法允许它们以任何顺序出现。然而,置于它们之上的语义规则引入了一些限制。例如,在变量声明中,必须始终有一个不是 cv 限定符(constvolatile)的类型说明符。也不能有超过一个存储类说明符(除了thread_local可以与staticor一起出现extern)。

请注意,decl 说明符序列位于任何复合类型语法(例如指针、引用、数组等)之前。例如,以下示例中标记了 decl 说明符的序列:

static const int *p;
|              |

char volatile static *(&p)[20];
|                  |

请注意,这volatile是一个 cv 限定符const,因此在您给出的示例中允许的原因volatile与 for 相同const。这些关键字也可以出现在声明的更深处(如 中int *volatile x;)。

按照惯例,我们首先编写存储类指定,然后在适当的情况下编写类型指定和 cv-qualifiers。我更喜欢在它们对应的类型说明符之后写我的 cv-qualifications ,因为它更一致。

您可能想阅读什么是声明和声明符以及标准如何解释它们的类型?.

于 2014-08-20T23:09:13.620 回答
2

这些部分实际上在标准中相当广泛地分开。static是一个存储类,如 §7.1.1/1 中所述:

storage-class-specifier:
    register
    static
    thread_local
    extern
    mutable

这在decl-specifier 中使用,如 §1.7 中所定义:

decl-specifier:
    storage-class-specifier
    type-specifier
    function-specifier
    friend
    typedef
    constexpr

decl-specifier-seq:
    decl-specifier attribute-specifier-seqopt
    decl-specifier decl-specifier-seq

因此,这允许static intint static指定一个类型。同样,您可以将友元函数声明为friend int f();or 或int friend f();

const或者volatile只能在您实际声明某些内容时参与,因此它属于第 8 节中的“声明符”。这部分语法足够长,我懒得格式化所有内容,但它指定了init-declarator-list在顶层,然后是declarator,然后(跳过几层)下降到cv-qualifierconstor volatile。至少根据我的阅读,它基本上允许constorvolatile与指定类型的其他事物自由混合。

于 2014-08-20T23:23:34.987 回答
0

好吧,以下是我的猜测。我试图解释这一点。

static int *ptr1;
int* static ptr2;

第一个意味着它是一个指针,指向一个静态整数。第二个意味着它是一个静态变量,具有整数指针类型。

我认为另一种方式应该有类似的解释。

于 2014-08-20T23:03:53.847 回答