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

Posted

技术标签:

【中文标题】命名空间范围内的静态关键字无用?【英文标题】:static keyword useless in namespace scope? 【发布时间】:2011-08-27 10:32:23 【问题描述】:
namespace N

   static int x = 5;

在命名空间范围内声明具有静态变量的重要性/用例是什么?

【问题讨论】:

我认为不鼓励使用static;改用未命名的命名空间。 @ereOn:不是真的。 C++03 已弃用它,但 C++11 已弃用它。为什么?因为它在某些方面很有用。 【参考方案1】:

我同意 Nawaz 的回答:static 关键字在命名空间中并非完全没用:它定义了变量与翻译单元的内部链接。

例如: header.h

namespace test
    static int i = 5;//definition is here.And there will be no multiple definition!
    void set_i();
    void print_i();

header.cpp

#include "header.h"
#include "iostream"
void test::set_i()

    i = 10;
    return;


void test:print_i()

    using namespace std;
    cout << "print_i is " << i << endl;
    return;

main.cpp

#include "header.h"
#include "iostream"
using std::cout;
int main()

    test::i = 20;
    test::set_i();
    cout << "i is " << test::i << endl; 
    test::print_i();
    return 0;

使用g++ -std=c++11 header.cpp main.cpp编译,不会得到multiple definition error。如果去掉static关键字再编译,肯定是multiple definition error。请运行程序并观察结果,您可能会感到惊讶。

static 关键字使每个包含接口头的 cpp 实现文件(翻译单元)都具有静态变量的内部链接副本。因此,即使您在命名空间中定义该变量,如果它是 static 关键字,也不会出现多重定义错误。(const 与前面没有 extern 相同,它定义了内部链接的变量,这就是宏的方式可以在 C++ 中丢弃)因此,在命名空间中定义的变量是隐式静态的说法是错误的,静态在命名空间中并非完全没用。因为每个翻译单元都有该变量的一份副本,所以会占用空间。

但是,未命名的命名空间可以使其他翻译单元无法访问其中的类声明,而 static 关键字不能“属性”一个类,因此这是未命名命名空间的一个优点。此外,您可以在嵌套命名空间中使用未命名命名空间来限制变量访问。未命名的命名空间旨在保护局部性,而不是提供接口。

【讨论】:

【参考方案2】:

C++ 标准§7.3.1.1/2:

static关键字的使用是 在 a 中声明对象时不推荐使用 命名空间范围(见附件 D);这 unnamed-namespace 提供了一个优越的 替代。

除非未命名的命名空间在未来的标准it will be undeprecated 中提供更好的替代方案以实现 C 兼容性。

【讨论】:

这不是在 2011 年被弃用了吗? 我相信 C++0x 标准在这种情况下不会弃用 static,不是吗? 在最后的草稿中,这一段是存在的,但被删除了,所以我不确定。 有趣。我想你不能对尚未最终确定的标准认为任何事情都是理所当然的。 @Neil 范围不是问题; static 不影响范围。 “类”(即:类的名称及其所有成员的名称)具有外部链接,除非它们是本地的(在函数中定义)。因此,如果我在我的翻译单元中定义 class C public: C(); ;,而您也这样做,C::C 在两者中都指代相同的实体。如果我们都定义它,我们可能会在链接时得到重复的定义。 (正式地,这是未定义的行为。)而且你无法让static 应用于一个类;这就是引入未命名命名空间的真正原因。【参考方案3】:

附录 D(兼容性功能)[C++03]

D2:在命名空间范围内声明对象时,不推荐使用 static 关键字。

如this 帖子中所述,使用未命名的命名空间。

static 关键字在 C 和 C++ 中的命名空间范围内赋予变量/对象的内部链接,正如其他人在他们的帖子中提到的那样。

附注: 根据最新草案 (n3290),该功能已不推荐。在 n3225 中,§7.3.1.1/2 存在但被删除。

【讨论】:

+1,此外,虽然没有特别的原因不能使用未命名的命名空间完成此操作,但一些编译器为 static 链接函数提供了更多诊断(例如在翻译中未使用符号时的警告单位)【参考方案4】:

其他人已经说过,还有一点微妙之处:静态引入了内部链接,而匿名命名空间则没有。

【讨论】:

【参考方案5】:

static 命名空间范围内的变量(全局或其他)具有内部链接。这意味着,它不能从其他翻译单元访问。它是声明它的翻译单元的内部

【讨论】:

这是一个更好的答案,因为它解释了 static 在命名空间范围内的作用。不是什么都不做,也不是没用。【参考方案6】:

与在全局命名空间中声明一个静态变量相同,但仅对特定命名空间是本地的。

【讨论】:

以上是关于命名空间范围内的静态关键字无用?的主要内容,如果未能解决你的问题,请参考以下文章

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

整个类范围内的 C++ 命名空间别名

命名空间内与类内的范围函数[重复]

实际场景中的代表:在命名空间范围内的类范围内

使用内核命名空间 PID 从全局范围中杀死进程

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