静态const与const的C ++语义


149

具体来说,在C ++中,例如之间的语义差异是什么:

static const int x = 0 ;

const int x = 0 ;

同时static用作链接和存储类说明符(即函数内部和外部)。


7
static可能是C ++中最重载的关键字。您的代码的含义差异很大,具体取决于它是在名称空间范围,类范围还是函数范围。您可能需要澄清一下。
sbi 2010年

1
@sbi:我以为我已经做到了。函数作用域(在这里是存储类说明符)和文件作用域(在这里是链接说明符)。对于这个问题,我并不是特别关心类成员和命名空间范围的变量,尽管如果有人觉得有一个有趣的区别,也可以随意讨论。
Clifford 2010年

@Clifford:对不起,我忽略了这些遗言。但是,这显示出您的一个误解:在C ++中,文件范围名称空间范围。如果在任何名称空间之外声明任何内容,则该名称将仅属于全局名称空间(并且可以通过前缀(前面::没有标识符)进行访问)。我不知道全局名称空间和嵌套在其中的任何名称空间之间的任何有意义的区别。当然没有关于static对象的任何东西。
2010年

1
链接可见性不同,通过互换使用它们,您将使与您交谈的人以及您自己也感到困惑。
Ben Voigt 2010年

1
@Ben,@sbi:我无意暗示文件范围静态链接是相同的,只是静态链接暗含了文件范围。从这个意义上说,作用域(或可见性)是静态和外部链接的属性,而不是两者的同义词。我认为最初的问题仍然很清楚并且结构合理,我们只是在讨论针对sbi的谦逊言论所作的评论。我们在这里讨论英语的不精确语义,而不是我的理解,所以我认为我们可以停止。
克利福德,2010年

Answers:


128

在文件范围内,C ++没有区别。 const将内部链接设置为默认值,并且所有全局变量都具有静态生存期。但是第一个变体在C中具有相同的行为,因此这可能是使用它的一个很好的理由。

在一个函数中,可以根据参数计算第二个版本。在C或C ++中,它不必像某些其他语言所要求的那样是编译时常量。

在一个类中,与函数基本相同。const可以在ctor-initializer-list中计算实例值。static const在启动初始化期间设置A ,在其余程序中保持不变。(注意:static成员的代码看起来有些不同,因为声明和初始化是分开的。)

请记住,在C ++中,它const表示只读,而不是常量。如果您有指向的指针const,则程序的其他部分可能会在您不查找时更改该值。如果使用定义了变量const,则初始化后没有人可以更改它,但是初始化仍然可以是任意复杂的。


1
有什么叫做文件作用域吗?我刚刚检查了$ 3.3,我认为最接近的是“命名空间范围”。我的理解正确吗?C ++ 03标准仅在附录中提及文件范围
Chubsdad 2010年

2
我建议文件范围是链接器而不是编译器的产物,因此在语言标准中可能不会引起太多关注。严格来说,它可能是“编译单元范围”。
克利福德,2010年

8
短语“ const表示只读,而不是常量”的值+1,即“编译器,如果您看到有人试图修改此const内容,请大声咆哮。” 这就是为什么某些东西可以同时常量和易失的原因。

5
更多的是“编译器,如果您看到我尝试修改此const内容(或授予他人许可)”,大声咆哮。在大多数情况下,const适用于变量的视图而不是变量本身,其他人可以具有const相同变量的非视图,并且编译器在修改变量时将保持沉默。
Ben Voigt 2010年

1
@Ben:请注意,C ++ 0x不会删除对的特定使用const,但是constexpr可以代替使用新的(以及在其他情况下)。实际上,C ++ 0x标准还将const在这种情况下使用的能力扩展到了非集成的“文字类型”。我认为我更喜欢constexpr在这些情况下使用,因为无论如何您都将破坏与C ++ 0x以前的编译器的向后兼容性。
Michael Burr

4

关于文件范围const隐含的C ++ 17标准草案static

这是在https://stackoverflow.com/a/3709257/895245中提到的内容的报价。

C ++ 17 n4659标准草案 6.5“程序和链接”:

3具有名称空间范围(6.3.6)的名称如果是

  • (3.1)—明确声明为静态的变量,函数或函数模板;要么,
  • (3.2)—非易失性,const限定类型的非内联变量,既未明确声明为extern,也未先前声明为具有外部链接;要么
  • (3.3)—匿名联合的数据成员。

附件C(信息性)兼容性,C.1.2第6条:“基本概念”提供了将其从C更改为以下原因的理由:

6.5 [也10.1.7]

更改:显式声明为const而不显式声明为extern的文件范围的名称具有内部链接,而在C中它将具有外部链接。

原理:由于const对象可以在C ++转换过程中用作值,因此此功能敦促程序员为每个const对象提供一个显式的初始化程序。此功能允许用户将const对象放入多个翻译单元中包含的源文件中。

对原始特征的影响:更改了定义明确的特征的语义。

转换困难:语义转换。

广泛使用:很少。

另请参见:为什么const在C ++中隐含内部链接,而在C语言中却不隐含?

您可能想在标头上执行的操作

详细解释于:C和C ++中的“常量静态”是什么意思?

  • C ++ 17之前的版本:extern在标头中,在cpp文件中定义
  • 发布C ++ 17:标头上的内联变量

谢谢,尽管与C ++ 98相比,即使在C ++ 17中我也不认为这是一个机会,并且在2010年提出了这个问题。此外,您的答案仅涉及静态作为链接说明符(在命名空间范围内) ,并专门询问有关不同上下文中语义的问题。
克利福德,

@Clifford是的,绝对早于C ++ 17,只是懒于阅读所有标准;-)将阐明文件范围的一部分。
西罗Santilli郝海东冠状病六四事件法轮功
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.