我想知道C ++如何使用它的const关键字。
我有以下功能定义。单独看起来很疯狂,但效果很好。
const int const * const Get(){ return new int(1); } const
我知道const的每个位置意味着什么,这个问题不是关于const关键字放置的意义。
我对使用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
为什么语言允许你这样做?
编辑: 此代码可以在Visual Studio 2013,Visual C ++编译器中编译。我不确定编译器的实际名称。
EDIT2:
所以答案是这是违反标准的。该代码仅使用/Za
选项编译。
我投票结束了这个问题。
答案 0 :(得分:10)
标准中不允许在同一类型说明符序列中明确重复const
。
[dcl.type] / 2(强调我的)
作为一般规则,在声明的完整decl-specifier-seq中最多允许一个类型说明符或 在type-specifier-seq或trailing-type-specifier-seq。
中...
- const可以与除自身之外的任何类型说明符组合。
有人可能会认为这可以从以下引用中获得(由@davidhigh找到):
[dcl.type.cv] / 1
有两个cv限定符,const和volatile。每个cv-qualifier在cv-qualifier-seq中最多只出现一次。如果cv-qualifier出现在decl-specifier-seq中,则声明的init-declarator-list不应为空。 [注意:3.9.3和8.3.5描述了cv限定符如何影响对象和函数类型。 - 尾注] 忽略冗余cv资格。 [注意:例如,这些可以由typedef引入。 - 结束说明]
但是,此规则允许通过模板或const
中的替换产生typedef
重复,而不是程序员明确键入的重复。
举一个例子:
const const int const const * const const Get(){ return new int(1); } const const
前四个const
都适用于int
,违反了上面发布的规则。
接下来的两个const
适用于指针,并且由同一规则无效。
最后两个const
甚至不是Get
声明的一部分。它们将应用于解析器下一步找到的任何内容,通过与上述相同的规则或其他C ++语法规则变为无效。
VS2013可以使用语言扩展编译此类代码,但这不是标准行为。 gcc 5.1.0和clang 3.5.1都会拒绝编译您的代码,并且都会提供合理的诊断。
答案 1 :(得分:3)
重新
“为什么语言允许您这样做?”
它没有。提供的代码是不是真正的代码。 E.g。
const int const * const Get(){ return new int(1); } const
(第一个示例)不会使用任何符合标准的编译器进行编译,原因有两个:
const
(int
)。const
是语法错误。Standardeese的第一点:C ++11§7.1.6/ 2,
“
const
可以与除自身之外的任何类型说明符组合使用。
答案 2 :(得分:1)
为什么呢?因为标准是这样说的。以下是[dcl.type.cv]的摘录,其中正好说明了这一点(强调我的):
有两个cv限定符,const和volatile。每个cv-qualifier在cv-qualifier-seq中最多只出现一次。 如果cv-qualifier出现在decl-specifier-seq中,则声明的init-declarator-list应为 不是空的。 [注意:3.9.3和8.3.5描述了cv限定符如何影响对象和函数类型。 - 结束说明] 忽略冗余cv资格。 [注意:例如,这些可以由typedef引入。 - 结束 注意]
例如,这在模板中很有意义。如果模板参数推导为const
,则很容易发生另一个const被添加到某个地方。
编辑:如上所述多次冗余,我的上述答案具有误导性,因为它不符合此条件。它被[dcl.type]中的规则所反对,该规则明确禁止明确键入const
限定符(请参阅@TartanLlama在其答案中的精细注释)。
编辑2 :规则的应用每个人似乎都同意状态:第一个冗余的const
是不允许的,如果它们仍然应该在某个地方发生,则会被忽略。
但是,这需要标准报价的优先级。
如果没有,人们也可以想到这样一个顺序:首先删除多余的const
,然后才应用不允许多个const
的规则(当然,这会导致后一条规则本身就是多余的。)
在这种情况下,显然,引用显示了它的解释方式。但是,作为迂腐,它不必像这样解释 - 除非标准引号中有某种形式的优先权。
答案 3 :(得分:0)
此功能声明(及其他)
const int const * const Get(){ return new int(1); } const;
将无法编译,因为根据C ++标准(7.1.6类型说明符,#2)
- const可以与任何类型说明符组合,除了它本身。
和(7.1.6.1 cv-qualifiers)
1有两个cv限定符,const和volatile。每个cv-qualifier 在cvqualifier- seq中最多出现一次。
在此声明中,例如限定符const与其自身结合
const int const * const Get(){ return new int(1); } const;
^^^^^ ^^^^^
此外,最后一个限定符放在错误的位置。:)
const int const * const Get(){ return new int(1); } const;
^^^^^
在皮带上应该有
const int const * const Get() const { return new int(1); };
^^^^^
或者在此声明中(如果正确放置cv-qualifier序列)至少cv-qualifier序列具有多个const限定符
const const int const const * const const Get() const const { return new int(1); };
^^^^^ ^^^^^
与C中的C ++相反,您可以在声明中组合多个限定符。简单地忽略冗余限定符。例如
const long const long const int const x = 10;
相当于
const long long int x = 10;
但是在C ++中,这个声明不会编译。
答案 4 :(得分:0)
两个单独的问题。
默认情况下,MSVC会针对重复的限定符而不是错误发出警告(C4114)。该标准允许这样做,因为所需要的只是一条诊断消息,并且警告满足了这一要求。
最终const
只有当它们实际上是后续声明的一部分时才会编译。例如:
const const int const const * const const Get(){ return new int(1); } const const
int main() {}
这实际上是
const const int const const * const const Get(){ return new int(1); }
const const int main() {}
这是"好的"模拟重复的限定符部分。