根据标准委员会的说法,为什么匿名命名空间不能完全替代namespace-static?

Nic*_*las 50 c++ c++11

根据这个答案,命名空间范围的静态变量在C++ 11中是未被完美的.也就是说,它们在C++ 03中被弃用,因为匿名命名空间被认为更好.但是C++ 11对它们不予重视.

为什么?N3296将其原因列为:

不应该弃用在命名空间范围中使用静态.匿名命名空间不足以替代该功能.

这显然是委员会接受的.为什么?什么是匿名命名空间不完全取代此功能?

我更喜欢那些有标准委员会讨论的文件或书面记录的答案.

Pub*_*bby 35

这是一个更深入的解释.

虽然7.3.1.1 [namespace.unnamed]表示的是,使用用于声明在命名空间范围变量static关键字的被推荐使用,因为未命名的命名空间提供了更好的选择,这是不太可能的特征将在可预见的未来的任何点被去除,特别是考虑到C兼容性问题.委员会应考虑取消弃用.

我知道的一个问题是匿名命名空间不能专门化命名空间块之外的模板.这就是为什么inline namespace被引入,虽然static也有效.此外,static与宏发挥很好.


Joh*_*itb 29

使用未命名的命名空间,您无法在当前所在的同一命名空间中提供可变的内部链接.static您可以使用.例如,以下使用未命名的命名空间不会给出全局变量内部链接

namespace { int a; } 
int a; // oops, no error!
Run Code Online (Sandbox Code Playgroud)

如果第一个a被声明为static,则a在全局范围内声明第二个的尝试将立即出错,因为第一个a已经存在于全局范围.

因此,要实现使身份唯一的工作,未命名的命名空间将实体放入不同的命名空间(除了影响它们的链接).static 影响链接,保留哪些函数和变量的成员名称不变.

  • @user2394284我想我不确定你的评论意味着什么或者它应该澄清什么。链接的定义是这样的..“当一个名称可能表示与另一个范围中的声明引入的名称相同时,则称该名称具有/链接/”。如果在另一个的定义中需要一个,那么断言一个与另一个无关似乎是一个很大的延伸。 (4认同)

Mar*_*utz 15

用户在战斗中的答案是未命名的命名空间中的名称(匿名命名空间的标准术语)具有外部链接,static在命名空间级别声明的名称具有内部链接.

内部链接有两个优点,其中只有一个未命名的命名空间提供:

  1. 它们使翻译单元的名称成为本地名称.我可以fun在不同的翻译单元中以不同的方式定义相同的功能,而不违反单一定义规则.此属性由未命名的命名空间中的名称共享,方法是使用唯一的命名空间名称对其进行装饰.

  2. 它们阻止名称进入全局符号表.这绝对是一种优化,但在实践中却是一个重要的优化.未命名的命名空间中的名称不共享此属性.

因此,通常,static用于其转换单元本地命名空间级别函数的程序为链接器生成较少的工作,并且可能比使用未命名的命名空间的等效程序执行得更快.

也就是说,您需要将未命名的命名空间用于要作为模板参数传递的类型,因为模板参数必须具有外部链接.

所以我通常会执行以下操作:将自由函数定义为static,但将类型放入未命名的命名空间中.

  • 我知道cppreference.com不是标准,但我不知道它们是错的,在http://en.cppreference.com/w/cpp/language/namespace#Unnamed_namespaces,他们说未命名的命名空间有内部链接.那么:内部还是外部? (3认同)
  • 感谢您的解释和分享您的惯常做法!我认为它可以被视为"最佳实践"之一. (2认同)
  • 代码如何执行得更快?你不是说它会更快地链接吗? (2认同)
  • 这是一个很好的答案,只是术语与标准不符。具体来说,该标准说未命名名称空间中的名称具有_internal_链接。我想您要说明的是,“静态”函数的名称通常甚至不会添加到链接器所需的符号表中。但是,未命名空间中的函数通常会添加到符号表中,但会被标记为内部函数或损坏的函数,从而实际上无法访问它们。 (2认同)
  • 事实上,未命名命名空间中的函数名称不需要与 `static` 函数不同地添加到符号表中。它们都有内部链接,并且都可以以相同的方式处理(至少由 GCC 处理)。我不相信这个答案是正确的。 (2认同)