简体   繁体   English

函数定义中的四倍“const”

[英]Quadruple “const” in function definition

I am wondering about how C++ uses its const keyword. 我想知道C ++如何使用它的const关键字。

I have the following function definition. 我有以下功能定义。 Which alone looks quite insane, but works just fine. 单独看起来很疯狂,但工作得很好。

const int const * const Get(){ return new int(1); } const

I am aware of what each placement of the const means, this question isn't about the meaning of the placement of the const keyword. 我知道const的每个位置意味着什么,这个问题不是关于const关键字的位置的意义。

I am quite confused by the use of the const keywords, because you can duplicate them. 我对使用const关键字感到困惑,因为你可以复制它们。

const int const const * const Get(){ return new int(1); } const

// or even

const const int const const * const const Get(){ return new int(1); } const const

// or even yet

const const const int const const const * const const const Get(){ return new int(1); } const const const

Why does the language allow you to do this? 为什么语言允许你这样做?

EDIT: This code can be compiled in Visual Studio 2013, Visual C++ compiler. 编辑:此代码可以在Visual Studio 2013,Visual C ++编译器中编译。 I am not sure about the actual name of the compiler. 我不确定编译器的实际名称。

EDIT2: So the answer is that this is against the standard. 编辑2:所以答案是这是违反标准的。 The code only compiles wihout using /Za option. 代码只编译wihout使用/Za选项。

I am voting to close the question. 我投票结束这个问题。

Explicitly repeating const in the same type specifier sequence is disallowed in the standard. 标准中不允许在相同类型说明符序列中明确重复const

[dcl.type]/2 (emphasis mine) [dcl.type] / 2(强调我的)

As a general rule, at most one type-specifier is allowed in the complete decl-specifier-seq of a declaration or in a type-specifier-seq or trailing-type-specifier-seq. 作为一般规则,在声明的完整decl-specifier-seq或类型说明符-seq或trailing-type-specifier-seq中最多允许一个类型说明符。

... ...

const can be combined with any type specifier except itself. - const可以与除自身之外的任何类型说明符组合使用。

One might think that this is allowed from the following quote (found by @davidhigh): 有人可能会认为这可以从以下引用中获得(由@davidhigh找到):

[dcl.type.cv]/1 [dcl.type.cv] / 1

There are two cv-qualifiers, const and volatile. 有两个cv限定符,const和volatile。 Each cv-qualifier shall appear at most once in a cv-qualifier-seq. 每个cv-qualifier在cv-qualifier-seq中最多只出现一次。 If a cv-qualifier appears in a decl-specifier-seq, the init-declarator-list of the declaration shall not be empty. 如果cv-qualifier出现在decl-specifier-seq中,则声明的init-declarator-list不应为空。 [ Note: 3.9.3 and 8.3.5 describe how cv-qualifiers affect object and function types. [注意:3.9.3和8.3.5描述了cv限定符如何影响对象和函数类型。 — end note ] Redundant cv-qualifications are ignored . - 尾注] 多余的cv资格被忽略 [ Note: For example, these could be introduced by typedefs. [注意:例如,这些可以由typedef引入。 — end note ] - 结束说明]

However, this rule is to allow const duplications which arise through substitution in templates or typedef s, not those explicitly typed by the programmer. 但是,此规则允许通过模板或typedef的替换产生const复制,而不是程序员明确键入的复制。

Taking one of your examples: 以你的一个例子为例:

const const int const const * const const Get(){ return new int(1); } const const

The first four const s all apply to the int , breaking the rule posted above. 前四个const都适用于int ,违反了上面发布的规则。

The next two const s apply to the pointer and are invalid by the same rule. 接下来的两个const适用于指针,并且由同一规则无效。

The final two const s are not even part of the declaration for Get . 最后两个const甚至不是Get的声明的一部分。 They will be applied to whatever the parser finds next, becoming invalid by either the same rules as above, or by other C++ syntax rules. 它们将应用于解析器下一步找到的任何内容,通过与上述相同的规则或其他C ++语法规则变为无效。

VS2013 may compile such code using language extensions, but this is not standard behaviour. VS2013可以使用语言扩展编译此类代码,但这不是标准行为。 gcc 5.1.0 and clang 3.5.1 will both refuse to compile your code and both provide a reasonable diagnostic. gcc 5.1.0clang 3.5.1都拒绝编译你的代码,并且都提供合理的诊断。

Re 回覆

Why does the language allow you to do this?" 为什么语言允许你这样做?”

it doesn't. 它没有。 The code presented is not real code . 提供的代码不是真正的代码 Eg 例如

const int const * const Get(){ return new int(1); } const

(the first example) will not compile with any standard-conforming compiler, for two reasons: (第一个示例)不会使用任何符合标准的编译器进行编译,原因有两个:

  • The multiple const s at the start (for the int ) are not permitted. 不允许在start(对于int )的多个const
  • The const at the end is a syntax error. 最后的const是语法错误。

Standardeese for the first point: C++11 §7.1.6/2, Standardeese的第一点:C ++11§7.1.6/ 2,

const can be combined with any type specifier except itself. const可以与除自身之外的任何类型说明符组合使用。

Why? 为什么? Because the standard says so. 因为标准是这样说的。 Here is an excerpt from [dcl.type.cv] which states exactly this (emphasis mine) : 这是[dcl.type.cv]的摘录,其中正好说明了这一点(强调我的):

There are two cv-qualifiers, const and volatile. 有两个cv限定符,const和volatile。 Each cv-qualifier shall appear at most once in a cv-qualifier-seq. 每个cv-qualifier在cv-qualifier-seq中最多只出现一次。 If a cv-qualifier appears in a decl-specifier-seq, the init-declarator-list of the declaration shall not be empty. 如果cv-qualifier出现在decl-specifier-seq中,则声明的init-declarator-list不应为空。 [ Note: 3.9.3 and 8.3.5 describe how cv-qualifiers affect object and function types. [注意:3.9.3和8.3.5描述了cv限定符如何影响对象和函数类型。 — end note ] Redundant cv-qualifications are ignored. - 尾注] 多余的cv资格被忽略。 [ Note: For example, these could be introduced by typedefs. [注意:例如,这些可以由typedef引入。 — end note ] - 结束说明]

This makes sense in templates, for example. 例如,这在模板中很有意义。 If the template parameter is deduced as const , it can easily happen that another const is added somewehere. 如果模板参数被推导为const ,则很容易发生另一个const被添加到某个地方。


EDIT : as noted several times and redundantly, my above answer is misleading in that it does not qualify here. 编辑 :正如多次提到的那样冗余,我的上述答案具有误导性,因为它不符合此处的条件。 It is opposed by the rule in [dcl.type] which explicitly disallows explicitly typed const qualifiers (see the fine comment by @TartanLlama in his answer). 它被[dcl.type]中的规则所反对,该规则明确禁止显式类型的const限定符(参见@TartanLlama在其答案中的精细注释)。


EDIT 2 : the application of the rule everyone seems to agree on states: first redundant const s are disallowed, and if they still should somewhere occur they are ignored. 编辑2 :规则的应用每个人似乎都同意状态:第一个冗余const是不允许的,如果它们仍然应该在某个地方发生,它们将被忽略。

This, however, requires a priority of the standard quotes. 但是,这需要标准报价的优先级。

Without, one could also think of an order like: first remove redundant const s, and only then apply the rule that multiple const s are not allowed (which, of course, would render the latter rule itself redundant). 如果没有,人们也可以想到一个命令:首先删除冗余const ,然后才应用不允许多个const的规则(当然,这会使后一个规则本身变得多余)。

In this case, obviously, the quote shows how it is meant to be interpreted. 在这种情况下,显然,引用显示了它是如何被解释的。 But, being pedantic, it does not have to be interpreted like this -- unless there is some form of priority in the standard quotes. 但是,作为迂腐, 它不必被解释为这样 - 除非标准报价中有某种形式的优先权。

This function declaration (and others) 这个函数声明(和其他)

const int const * const Get(){ return new int(1); } const;

will not compile because according to the C++ Standard (7.1.6 Type specifiers, #2) 将无法编译,因为根据C ++标准(7.1.6类型说明符,#2)

— const can be combined with any type specifier except itself . - const可以与除自身之外的任何类型说明符组合使用。

and (7.1.6.1 The cv-qualifiers) 和(7.1.6.1 cv-qualifiers)

1 There are two cv-qualifiers, const and volatile. 1有两个cv限定符,const和volatile。 Each cv-qualifier shall appear at most once in a cvqualifier- seq. 每个cv-qualifier 最多只能在cvqualifier-seq中出现一次

In this declaration for example qualifier const is combined with itself 在此声明中,例如限定符const与其自身组合

const int const * const Get(){ return new int(1); } const;
^^^^^     ^^^^^

Moreover the last qualifier is placed in the wrong place.:) 而且最后一个限定符放在错误的位置。:)

const int const * const Get(){ return new int(1); } const;
                                                    ^^^^^ 

At leats there should be 在leats应该有

const int const * const Get() const { return new int(1); };
                              ^^^^^ 

Or in this declaration (if to place the cv-qualifier sequence correctly) at least cv-qualifier sequence has more than one const qualifier 或者在这个声明中(如果正确放置cv-qualifier序列)至少cv-qualifier序列有多个const限定符

const const int const const * const const Get() const const { return new int(1); };
                                                ^^^^^ ^^^^^

Opposite to C++ in C you may combine several qualifiers in a declaration. 与C中的C ++相反,您可以在声明中组合多个限定符。 The redundant qualifiers are simply ignored. 简单地忽略冗余限定符。 For example 例如

const long const long const int const x = 10;

that is equivalent to 这相当于

const long long int x = 10;

However in C++ this declaration will not compile. 但是在C ++中,这个声明不会编译。

Two separate issues. 两个单独的问题。

  1. By default MSVC issues a warning ( C4114 ) for repeated qualifiers rather than an error. 默认情况下,MSVC会针对重复的限定符而不是错误发出警告( C4114 )。 The standard permits this since all that's required is a diagnostic message, and a warning satisfies this requirement. 标准允许这样做,因为所需要的只是一条诊断消息,并且警告满足此要求。

  2. The final const s compile only when they are actually part of a subsequent declaration. 最后的const只在它们实际上是后续声明的一部分时编译。 For instance: 例如:

     const const int const const * const const Get(){ return new int(1); } const const int main() {} 

    This is actually 这实际上是

     const const int const const * const const Get(){ return new int(1); } const const int main() {} 

    which is "OK" modulo the repeated qualifiers part. 这是“OK”模数重复的限定符部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM