【问题标题】:C++ semantics of `static const` vs `const``static const` 与 `const` 的 C++ 语义
【发布时间】:2010-09-14 13:16:20
【问题描述】:

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

static const int x = 0 ;

和

const int x = 0 ;

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

【问题讨论】:

  • static 可能是 C++ 中最重载的关键字。您的代码的含义根据它是在命名空间范围、类范围还是在函数范围内变化很大。你可能想澄清一下。
  • @sbi:我以为我已经做到了。函数范围(它是存储类说明符)和文件范围(它是链接说明符)。关于这个问题,我并不特别关心类成员和命名空间范围的变量,尽管如果有人觉得有一个有趣的区别,也可以随意讨论。
  • @Clifford:很抱歉我忽略了最后的话。但是,这暴露了您的一个误解:在 C++ 中,文件范围 是 命名空间范围。如果您在任何命名空间之外声明任何内容,它将仅属于 全局命名空间(并且可以通过前缀 :: 访问,前面没有标识符)。我不知道全局命名空间和嵌套在其中的任何命名空间之间有任何有意义的区别。当然没有任何关于 static 的对象。
  • linkage 与 visibility 不同,如果将它们互换使用,您会混淆与您交谈的人,也可能会混淆您自己。跨度>
  • @Ben, @sbi:我并不是要暗示 文件范围 和 静态链接 是相同的,只是静态链接 暗示文件范围。从这个意义上说,范围(或可见性)是静态和外部链接的属性,而不是两者的同义词。我觉得最初的问题仍然清晰且结构良好,我们只是在讨论为回应 sbi 有点居高临下的言论而提出的 cmets。我们在这里讨论的是不精确的英语语义,而不是我的理解,所以我想我们可以停下来了。

标签: c++


【解决方案1】:

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

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

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

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

【讨论】:

  • 有什么叫做文件作用域的吗?我只是检查 $3.3,我认为最接近的是“命名空间范围”。我的理解对吗? C++03 标准仅在附录中提及文件范围
  • 我建议 file scope 是链接器而不是编译器的人工制品,因此在语言标准中可能不会受到太多关注。严格来说可能是“编译单元范围”。
  • +1 表示“const 表示只读,而不是常量”,即“编译器,如果你看到有人试图修改这个 const 东西,请大声吠叫。”这就是某些东西可以同时是 const 和 volatile 的原因。
  • 它更像是“编译器,如果你看到我尝试修改这个 const 东西(或允许其他人这样做)”,非常大声地吠叫。在大多数情况下,const 应用于变量的视图而不是变量本身,其他人可以拥有同一变量的非const 视图,编译器在修改它时会保持沉默。跨度>
  • @Ben:需要明确的是,C++0x 并没有删除 const 的特定用途,但可以使用新的 constexpr 代替(在其他情况下也是如此) .实际上,C++0x 标准也将在该场景中使用 const 的能力扩展到非整数“文字类型”。对于这些情况,我想我更喜欢使用 constexpr,因为无论如何你都会破坏与 C++0x 之前的编译器的向后兼容性。
【解决方案2】:

const 上的 C++17 标准草案在文件范围内暗示 static

这是引用的内容:https://stackoverflow.com/a/3709257/895245

C++17 n4659 standard draft6.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 对象。

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

转换难度:语义转换。

使用的广泛程度:很少。

另见:Why does const imply internal linkage in C++, when it doesn't in C?

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

详解于:What does 'const static' mean in C and C++?

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

【讨论】:

  • 谢谢,尽管我认为即使与 C++98 相比,这在 C++17 中也不是一个机会,而且这个问题是在 2010 年提出的。此外,您的答案仅涉及静态为链接说明符(在命名空间范围内),以及专门针对不同上下文中的语义提出的问题。
  • @Clifford 是的,肯定早于 C++17,只是懒得阅读所有标准;-) 将澄清文件范围部分。
猜你喜欢
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 2018-10-04
  • 2012-12-26
  • 2011-03-12
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多