c++的一个特性是能够创建未命名(匿名)的名称空间,如下所示:

namespace {
    int cannotAccessOutsideThisFile() { ... }
} // namespace

您可能会认为这样的特性毫无用处——因为不能指定名称空间的名称,因此不可能从外部访问其中的任何内容。但是,这些未命名的名称空间可以在创建它们的文件中访问,就像对它们有一个隐式的using子句一样。

我的问题是,为什么或者什么时候这比使用静态函数更可取?或者它们本质上是做同一件事的两种方式?


当前回答

就我个人而言,我更喜欢静态函数而不是无名称的名称空间,原因如下:

It's obvious and clear from function definition alone that it's private to the translation unit where it's compiled. With nameless namespace you might need to scroll and search to see if a function is in a namespace. Functions in namespaces might be treated as extern by some (older) compilers. In VS2017 they are still extern. For this reason even if a function is in nameless namespace you might still want to mark them static. Static functions behave very similar in C or C++, while nameless namespaces are obviously C++ only. nameless namespaces also add extra level in indentation and I don't like that :)

所以,我很高兴看到静态函数不再被弃用了。

其他回答

我最近开始在代码中用匿名名称空间替换静态关键字,但很快就遇到了一个问题,即名称空间中的变量在调试器中不再可用。我使用的是VC60,所以我不知道其他调试器是否没有问题。我的解决方法是定义一个“模块”命名空间,在那里我给它我的cpp文件的名字。

例如,在我的xmlutil_cpp文件中,我定义了一个名称空间XmlUtil_I{…}用于我的所有模块变量和函数。这样我就可以在调试器中应用XmlUtil_I::资格来访问变量。在本例中,_I将其与公共名称空间区分开来,例如我可能希望在其他地方使用的XmlUtil。

我认为,与真正的匿名方法相比,这种方法的潜在缺点是,有人可能会在其他模块中使用名称空间限定符,从而违反所需的静态作用域。我不知道这是否是一个主要的问题。

将方法放在匿名名称空间中可以防止您意外地违反One Definition Rule,允许您不必担心将您的helper方法命名为与您可能链接的其他方法相同的方法。

而且,正如luke所指出的,标准更喜欢匿名名称空间而不是静态成员。

c++ 98标准不赞成为此目的使用static关键字。静态的问题在于它不适用于类型定义。它也是一个重载关键字,在不同的上下文中以不同的方式使用,因此未命名的名称空间简化了一些事情。

我刚才在看你的问题时才了解到这个特点,我只能猜测。这似乎比文件级静态变量提供了几个优势:

匿名名称空间可以嵌套在另一个名称空间中,提供多级保护,使符号无法逃脱。 可以在同一个源文件中放置多个匿名名称空间,从而在同一个文件中创建不同的静态级作用域。

我想知道是否有人在实际代码中使用过匿名名称空间。

根据我的经验,我只想指出,虽然这是c++将以前的静态函数放入匿名名称空间的方式,但旧的编译器有时会在这方面遇到问题。我目前正在使用一些用于目标平台的编译器,更现代的Linux编译器可以很好地将函数放置到匿名名称空间中。

但是在Solaris上运行的旧编译器有时会接受它,有时会将其标记为错误,直到未来未指定的版本发布。我担心的不是这个错误,而是它在接受错误时可能会做什么。因此,在全面现代化之前,我们仍然使用静态(通常是类作用域)函数,我们更喜欢匿名名称空间。