【问题标题】:Linkage of symbols within anonymous namespace within a regular namespace常规命名空间内匿名命名空间内的符号链接
【发布时间】:2011-05-10 00:36:49
【问题描述】:

在 C++ 中,将函数或变量放入匿名命名空间会使其内部链接,即。 e.与在文件级别声明 static 相同,但惯用 C++。

普通命名空间中的匿名命名空间呢?它仍然保证内部链接吗?

// foo.cpp

void func1() {
    // external linkage
}

static void func2() {
    // internal linkage
}

namespace {
    void func3() {
        // internal linkage
    }
}

namespace ns1 {
    void func4() {
        // external linkage
    }

    namespace {
        void func3() {
            // still internal linkage?
        }
    }
}

【问题讨论】:

  • 错误的假设。匿名命名空间内的变量具有外部链接,除非声明为 static
  • @MSalters:我认为对于 C++11,这已经改变了。 §3.5/4: An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage.
  • @legends2k:这是另一个更改的一部分,它使这些名称作为模板参数有效(在 C++03 中,模板参数需要外部链接,这由匿名命名空间中定义的常量来满足)

标签: c++ namespaces anonymous linkage


【解决方案1】:

匿名命名空间中的实体不一定具有内部链接;他们实际上可能有外部联系。

由于未命名的命名空间的名称对于编译它的翻译单元来说是唯一的,所以您不能从该翻译单元外部引用其中声明的实体,无论它们的链接是什么。

C++ 标准说(C++03 7.3.1.1/note 82):

虽然未命名命名空间中的实体可能具有外部链接,但它们实际上是由其翻译单元唯一的名称限定的,因此永远无法从任何其他翻译单元看到。

【讨论】:

  • 快速跟进:您知道内部链接是否有助于编译器为其优化做出更好的代码转换决策,还是不是问题?
  • @Alex B:这是个好问题。我的猜测是,如果编译器或链接器可以对具有内部链接的实体执行优化,他们可以对未命名命名空间中的实体执行相同的优化。不过,我不能肯定地说。这里的其他人会比我更了解。
【解决方案2】:

C++11(草案 N3337)§3.5/4:(强调我的)

未命名的命名空间或在未命名的命名空间中直接或间接声明的命名空间具有内部链接。所有其他命名空间都有外部链接。如果名称为

——一个变量;或

——一个函数;或

— 命名类(第 9 条),或在 typedef 声明中定义的未命名类,其中该类具有用于链接目的的 typedef 名称(7.1.3);或

— 命名枚举 (7.2),或在 typedef 声明中定义的未命名枚举,其中枚举具有用于链接目的的 typedef 名称 (7.1.3);或

— 属于具有链接的枚举的枚举数;或

——一个模板。

这保证任何未命名的命名空间都有内部链接。

普通命名空间中的匿名命名空间呢?它仍然保证内部链接吗?

虽然在命名(普通)命名空间内,但它是一个未命名(匿名)命名空间,因此保证按照 C++11 标准具有内部链接。


将函数或变量放入匿名命名空间会使其内部链接,即。 e.与在文件级别将其声明为静态相同,但符合 C++ 的习惯。

在 C++11 中,static 在这种情况下的使用是不赞成使用的;虽然unnamed namespace is a superior alternative to static, there're instances where it failsstatic 补救; inline namespace was introduced in C++11 来解决这个问题。

【讨论】:

    【解决方案3】:

    $3.5/3 - “具有命名空间的名称 范围(3.3.6)有内部链接如果 这是

    的名字

    ——一个变量, 函数或函数模板是 显式声明为静态的;或者,

    ——一个 显式声明的变量 const 且均未明确声明 extern 之前也没有声明过 外部链接;或

    ——一个数据成员 一个匿名工会的成员。

    所以,我怀疑您的程序中的任何名称“func3”和“func4”是否有内部链接。他们有外部联系。但是,只是不能按照詹姆斯的引用从其他翻译单位引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-10
      • 1970-01-01
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多