3

我听说它断言在 C++ 中使用未命名的命名空间来定义函数并确保不能从定义它们的编译单元外部调用它们在非常大的代码环境中不好,因为它们会导致符号表增长通过在 C++ 编译器在未命名时提供的自动生成的命名空间中包含这些符号的条目而不必要地大。

namespace {
  // This function can only be accessed from hear to the end of 
  // any compilation unit that includes it.
  void functionPerhapsInsertedIntoSymbolTable() {
    return;
  }
}

这可能是因为上述内容应该与执行以下操作相同:

namespace randomlyGenerateNameHereNotCollidingWithAnyExistingNames {
  // This function can only be accessed from hear to the end of
  // any compilation unit that includes it.
  void functionPerhapsInsertedIntoSymbolTable() {
    return;
  }
}
using randomlyGenerateNameHereNotCollidingWithAnyExistingNames;

然而,真的那么简单吗,编译器是否需要为生成的命名空间名称中的符号创建符号表条目?

相反,在这种情况下,我听说它建议使用静态声明:

// This function can only be accessed from hear to the end of
// any compilation unit that includes it.
static void functionNotInsertedIntoSymbolTable() {
  return;
}

在函数之前使用静态声明而不是将其放置在未命名的命名空间中是否具有使函数在定义它的编译单元之外无法访问的相同效果?除了可能不会导致符号表增长之外,这两种方法之间是否有任何区别?

由于未命名的名称空间导致的符号表膨胀问题只是 C++ 的某些实现中的一个错误,还是标准要求编译器以某种方式为此类函数创建条目?如果这种膨胀被认为是一个错误,那么是否有已知的编译器不存在这问题?

4

2 回答 2

4

在函数之前使用静态声明而不是将其放置在未命名的命名空间中是否具有使函数在定义它的编译单元之外无法访问的相同效果?

是的。

命名空间static- 在 C++03 中被弃用,取而代之的是未命名的命名空间,但实际上在 C++11中被弃用,因为每个人都意识到它们只是同一个东西并且弃用没有任何目的。

这两种方法有什么区别吗

不,不是。由于使用了命名空间,名称查找可能会有一些细微的差别,但我现在想不出来。

除了可能不会导致符号表增长?

由于这是一个language-lawyer没有明显实际问题需要解决的问题,我不得不指出,C++ 语言没有符号表的概念,因此没有表明这种效果。

在您拥有数以万计的未命名命名空间之前,它也不会产生任何明显的影响;你?

于 2013-01-17T18:20:07.807 回答
0

未命名的命名空间和命名空间级别静态的弃用的原因是命运多舛的导出关键字。

导出模板所依赖的所有内容都必须在实例化点可链接访问,这很可能在不同的源文件中。未命名的命名空间允许静态的“私有化”方面,同时仍保留导出模板的链接。

现在导出已在 C++2011 中删除,我很确定未命名命名空间的外部链接要求已被删除,它现在的行为与命名空间级别的静态完全相同。更熟悉该标准的人可以确认/反驳这一点。

于 2013-01-17T18:38:49.653 回答