【问题标题】:Are objects in anonymous namespace implicitly static?匿名命名空间中的对象是隐式静态的吗?
【发布时间】:2012-11-04 00:10:23
【问题描述】:

从 C++11 标准的角度来看,对象状态/属性之间是否存在技术差异:

namespace
{
   int foo;
   const int bar = 42;
}

namespace
{
   static int foo;
   static const bar = 42;
}

?


从这里的问题和答案中,我相信匿名命名空间中的对象是隐式静态的,但是有人告诉我它只是内部的链接,编译器不会将对象视为标记为静态的对象,其含义类似于它的含义将实现对象构造。所以我需要一些关于它真正含义的细节,如果在匿名命名空间中使用和不使用静态之间存在差异。

【问题讨论】:

  • 理论上,在匿名namespace 中声明的extern 变量是简单的static 变量的优越 替代方案。这就是为什么“静态全局变量”在 C++11 之前被弃用的原因。然而,“未命名命名空间内的外部变量”并不是“静态全局变量”的确切替换,它们是在 C++11 之后被带回来的!

标签: c++ c++11


【解决方案1】:

有一个很大的区别:与static,名字有内部联系;没有它,它具有外部链接(但在您不能在另一个翻译单元中引用的命名空间中)。区别并不总是很重要,但在某些情况下确实会发挥作用:例如,如果您有一个带有 int* 参数的模板,如果 foo 声明为 @987654326,则您不能在 &foo 上实例化它@。

编辑:

正如 Steve Jessop 所指出的,这仅适用于 C++03。 C++11 确实在这里做出了改变。虽然不知道为什么;我发现 C++03 规范更加连贯——某些东西所在的命名空间不应该影响链接。

【讨论】:

  • 您的意思是,仅在 C++03 中对吧?如果这个stackoverflow.com/questions/10832940/… 是正确的,那么它是C++11 中的外部链接(我应该将这个问题标记为C++11)
  • 链接没有改变。另一方面,我认为 C++11 确实允许将具有外部链接的符号用作模板参数。 (C++03 肯定不会,我必须明确标记 const 变量 extern 才能使用它们。)
  • 但是在阅读 Steve Jessop 的回答后,看起来他们确实在 C++11 中改变了这一点。 (实际上,因为您可以使用具有内部链接的名称作为模板参数,所以我认为这没有什么区别。)
  • 詹姆斯,您可能想在回答中澄清这一点,而不是在评论中。
  • @JohannesSchaub-litb 给定格式(使用较小字体的 cmets),您可能是对的。我会这样做的。 (我更习惯新闻组的格式,一旦发布就无法修改任何内容,但后续出现的权重相同,而不是次要的。)
【解决方案2】:

C++11、3.5/4:

未命名的命名空间或直接或间接声明的命名空间 在未命名的命名空间内具有内部链接。所有其他命名空间 有外部联系。具有命名空间范围的名称尚未 上面给定的内部链接与封闭的链接具有相同的链接 命名空间,如果它是一个变量的名字......

所以在 C++11 中,你的两个 foo 对象都有内部链接。在 C++03 中,第一个有外部链接。

无论联动,它都有静态存储时长。

我认为标准中没有“将对象视为标记为静态”之类的东西,所以我无法回答。如果您在标准中发现一些文本提到对象是否“标记为静态”并且没有具体提到链接或存储持续时间,那么请引用它,我可以给您一个意见:-)

【讨论】:

  • 与 C++03 相比,这是一个非常受欢迎的变化。刚刚在我的目标文件中检查了nm 的输出,来自未命名命名空间的符号确实具有内部链接。
  • 在C++03中,没有命名空间的名称,如何从其他翻译单元访问它?
  • @Chubsdad:为每个不同的翻译单元生成一个唯一的名称,因此您实际上无法访问它。因此,这种联系非常……令人惊讶。
  • @MatthieuM:直到您意识到这是因为在 C++03 中使用具有内部链接的对象的地址作为模板参数是无效的,这才令人惊讶。然后它从令人惊讶变为令人讨厌。
  • @SteveJessop 我刚刚添加了匿名命名空间中的对象为 const 的情况。我认为这是等效的代码,但是您能否在答案中确认(或反驳)?
猜你喜欢
  • 1970-01-01
  • 2012-11-20
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多