为啥未命名的命名空间是静态的“优越”替代品? [复制]

Posted

技术标签:

【中文标题】为啥未命名的命名空间是静态的“优越”替代品? [复制]【英文标题】:Why an unnamed namespace is a "superior" alternative to static? [duplicate]为什么未命名的命名空间是静态的“优越”替代品? [复制] 【发布时间】:2011-06-26 00:33:13 【问题描述】:

C++ 标准中的 $7.3.1.1/2 部分内容如下:

static关键字的使用是 在 a 中声明对象时不推荐使用 命名空间范围;未命名的命名空间 提供了更好的选择。

我不明白为什么一个未命名的命名空间被认为是更好的选择?理由是什么?我很早就知道标准是怎么说的,但我从来没有认真考虑过,即使我在回答这个问题时也是如此:Superiority of unnamed namespace over static?

正如我在answer 中描述的那样,它是否被认为是优越的,因为它也可以应用于用户定义的类型?还是还有其他一些我不知道的原因?我问这个,特别是因为这是我在回答中的推理,而标准可能有其他考虑。

【问题讨论】:

我也想知道这个。我猜它只是因为函数定义不推荐使用静态而更优越。您还可以使用未命名的命名空间定义本地类。 我很困惑。您似乎对另一个问题提供了一个很好的答案。你脑子里到底有什么没有答案? @Marcelo Cantos:我编辑了我的问题。 :-) 或***.com/questions/4422507/… 如果有的话,这个问题应该保留并且应该关闭 4422507,因为在这里我们看到了列出的真正原因,而不仅仅是指向标准的指针。 【参考方案1】: 正如您所提到的,命名空间适用于任何事物,而不仅仅是函数和对象。 正如 Greg 所指出的,static 已经意味着太多东西了。 命名空间提供了一种统一且一致的方式来控制全局范围内的可见性。您不必为同一件事使用不同的工具。 当使用匿名命名空间时,函数/对象名称将被正确修改,这使您可以在取消修改后在符号表中看到类似“(匿名命名空间)::xyz”的内容,而不仅仅是“xyz”带有静态链接。 正如下面的 cmets 所指出的,不允许使用静态的东西作为模板参数,而使用匿名命名空间就可以了。 更多?可能吧,但我现在想不出别的了。

【讨论】:

+1。此外,C++ 不允许将类型和指向具有内部链接(静态)的对象或函数的指针/引用用作模板参数。用匿名命名空间替换静态仍然会“隐藏”其他翻译单元的内容,但它们(大部分)保持外部链接,因此可以用作模板参数。但我想说匿名命名空间的主要目的可能是摆脱静态的重载含义之一。 @sellibitze,非常有趣,将其添加到答案中。只需澄清一点:“具有内部链接的类型”是什么意思?类型不能具有内部(静态?)链接的要点之一是什么? 这可能是我的一个错误。我刚刚检查了 C++ 标准草案,似乎命名类型总是有外部链接。但是内部和外部链接的定义与匿名命名空间所实现的结合起来似乎有点矛盾。 @sellibitze,我对链接的了解有点模糊,但我注意到readelf -s 在静态和匿名命名空间变量的“绑定”列中输出 LOCAL。对于全局变量,它说 GLOBAL。但这并不能阻止 GCC 允许匿名命名空间变量作为模板参数,而不是静态参数,所以你的观点仍然有效。 为什么“静态意味着太多东西”是命名空间优越的一个很好的理由?【参考方案2】:

一个原因可能是static已经有太多的含义(我至少可以数出三个)。由于匿名命名空间可以封装包括类型在内的任何内容,因此它似乎优于 static 解决方案。

【讨论】:

"static 已经有太多含义了(我至少可以数出三个)。" 我只看到了 2 个不同的含义。跨度> @curiousguy:符号链接;局部变量持久性;类方法。 我将“持久”变量和静态成员函数视为相同想法的情况:声明在词法上位于范围(函数或类)内,但其运行时行为不是声明的通常行为在那个范围内。顺便说一句,特定于类的运算符 new 和 delete 通常不声明为静态的,但根据定义始终是静态的。 @curiousguy:有 namespace-static,这意味着全局对象的存储仅限于翻译单元。有成员静态,这意味着类的成员不是类实例的一部分(并且静态成员函数不会得到this)。还有局部静态,这意味着定义的变量在函数调用中是持久的,但它的 lifetime 仅在第一次遇到时才开始。 namespace-static 的生命周期从程序执行开始时开始,在 main 之前(就像常规全局变量一样)。所以不,这是 3 个定义。 @NicolBolas 没错,有3个定义不能完全统一,但最后两个是相关的。 static 只有两种完全不相关的用法:“仅限于翻译单元”和“不是正常的生命周期规则”。【参考方案3】:

我认为有两个原因:

static 有两种不同的含义:在类范围内,表示由整个类共享,而在文件/函数范围内,它会影响可见性/存储... 未命名的命名空间允许声明新的structclasstypedef

但有一点,委员会对此表示反对:staticn3225 中不再被标记为已弃用。

【讨论】:

能否详细说明第二点? @Nawaz: namespace typedef int MyType; ?还是委员会删除deprecated 注释?

以上是关于为啥未命名的命名空间是静态的“优越”替代品? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥要将类型放在未命名的命名空间中?

什么时候适合在 C++ 中使用静态(通过未命名的命名空间)?

名称空间

JAXB:为啥在生成的 xml 文档中未使用定义的命名空间前缀?

C++ Primer 5th笔记(chap 18 大型程序工具)未命名的命名空间unnamednamespace

命名空间范围内的静态关键字无用?