根据标准委员会的说法,为什么匿名名称空间不能充分替代静态名称空间?
Why are anonymous namespaces not a sufficient replacement for namespace-static, according to the standards committee?
根据这个答案,命名空间作用域的静态变量在c++ 11中没有被弃用。也就是说,它们在c++ 03中被弃用了,因为匿名命名空间被认为更好。但是c++ 11不推荐它们。
为什么?N3296将此原因列出如下:
不应该反对在命名空间范围内使用static。匿名命名空间不足以替代该功能。
这显然被委员会接受了。为什么?为什么匿名名称空间不能完全取代这个功能呢?
我更希望答案有一些标准委员会讨论的文档或书面记录。
这是一个更深入的解释。
虽然7.3.1.1[命名空间。声明不赞成使用static关键字在命名空间范围内声明变量,因为未命名的命名空间提供了一个更好的选择,在可预见的将来,这个特性不太可能被删除,特别是考虑到C的兼容性问题。委员会应考虑取消弃用。
我知道的一个问题是,匿名命名空间不能专门化命名空间块之外的模板。这就是引入inline namespace
的原因,尽管static
也可以工作。此外,static
可以很好地处理宏。
对于未命名的名称空间,您不能在当前所在的名称空间内提供变量内部链接。对于static
,你可以。例如,以下未命名名称空间的使用不会提供全局变量的内部链接
namespace { int a; }
int a; // oops, no error!
如果第一个a
被声明为static
,那么尝试在全局作用域中声明第二个a
将立即出错,因为第一个a
已经在全局作用域中存在。
因此,为了实现使标识唯一的工作,未命名的名称空间将实体放置到不同的名称空间中(除了影响它们的链接之外)。static
只有影响链接,函数和变量所属的命名空间保持不变。
一线用户的回答是,未命名的名称空间(匿名名称空间的标准术语)中的名称具有外部链接,而在名称空间级别声明static
的名称具有内部链接。
内部链接有两个优点,其中只有一个是未命名的名称空间提供的:
-
它们使翻译单元的名称本地化。我可以在不同的翻译单元中对同一个函数
fun
进行不同的定义,而不违反单一定义规则。此属性由未命名命名空间中的名称共享,方法是使用唯一的命名空间名称来修饰它们。 -
它们阻止名称进入全局符号表。这是一个严格的优化,但在实践中很重要。
因此,一般来说,使用static
作为其翻译单元局部命名空间级函数的程序为链接器生成的工作更少,并且可能比使用未命名命名空间的等效程序执行得更快。
也就是说,对于想要作为模板参数传递的类型,您需要使用未命名的名称空间,因为模板参数必须具有外部链接。
所以我通常这样做:将自由函数定义为static
,但将类型放入未命名的命名空间。
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么我的for循环不能正确获取argv
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 为什么我不能在 FOR LOOP 中使用 i/10,C++?
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 是否可以将函数导入命名空间,但不能导出它?
- 命名空间:不能在没有对象的情况下调用成员函数
- 通用 lambda 不能在命名空间中使用
- 为什么我不能在标头中只定义一个非常量 gloabal 变量?如果我使用命名空间,为什么我必须声明它"extern"?
- 无法使用名称空间,也不能在我的.h文件中包含标准的C 库
- 为什么我不能将该操作员的过载与结构相同的命名空间
- 为什么我不能在以下代码中提供空间作为输入?
- (C++)不能引用命名空间内的枚举类
- 为什么不能引用c++中的嵌入命名空间
- 为什么我不能将命名空间放在父类构造函数调用中?
- 根据标准委员会的说法,为什么匿名名称空间不能充分替代静态名称空间?
- 为什么语句不能出现在命名空间范围内
- 不能将 math.h 放在命名空间中
- Boost::managed_mapped_file不能分配所有已增长的空间