我刚刚加入了一个新的c++软件项目,我正在试图理解设计。该项目经常使用未命名的名称空间。例如,在类定义文件中可能会出现这样的情况:

// newusertype.cc
namespace {
  const int SIZE_OF_ARRAY_X;
  const int SIZE_OF_ARRAY_Y;
  bool getState(userType*,otherUserType*);
}

newusertype::newusertype(...) {...

可能导致使用未命名名称空间的设计考虑因素是什么?优点和缺点是什么?


当前回答

Unnamed namespace limits access of class,variable,function and objects to the file in which it is defined. Unnamed namespace functionality is similar to static keyword in C/C++. static keyword limits access of global variable and function to the file in which they are defined. There is difference between unnamed namespace and static keyword because of which unnamed namespace has advantage over static. static keyword can be used with variable, function and objects but not with user defined class. For example:

static int x;  // Correct 

But,

static class xyz {/*Body of class*/} //Wrong
static structure {/*Body of structure*/} //Wrong

但是对于未命名的名称空间也可以这样。 例如,

 namespace {
           class xyz {/*Body of class*/}
           static structure {/*Body of structure*/}
  } //Correct

其他回答

未命名的名称空间是将标识符转换单元设置为本地的实用工具。它们的行为就像你要为命名空间的每个翻译单元选择一个唯一的名称:

namespace unique { /* empty */ }
using namespace unique;
namespace unique { /* namespace body. stuff in here */ }

使用空主体的额外步骤很重要,因此您已经可以在名称空间主体中引用该名称空间中定义的标识符,如::name,因为using指令已经发生。

这意味着你可以在多个翻译单元中拥有名为help的免费函数,并且它们不会在链接时发生冲突。其效果几乎与使用C中使用的static关键字相同,您可以将其放入标识符声明中。未命名的名称空间是一个更好的选择,它甚至能够使类型转换单元成为本地的。

namespace { int a1; }
static int a2;

两个a都是翻译单元本地的,不会在链接时发生冲突。但不同之处在于匿名名称空间中的a1获得了唯一的名称。

在comeau-computing上阅读优秀的文章,为什么使用未命名的名称空间而不是静态名称空间?镜子(Archive.org)。

Unnamed namespace limits access of class,variable,function and objects to the file in which it is defined. Unnamed namespace functionality is similar to static keyword in C/C++. static keyword limits access of global variable and function to the file in which they are defined. There is difference between unnamed namespace and static keyword because of which unnamed namespace has advantage over static. static keyword can be used with variable, function and objects but not with user defined class. For example:

static int x;  // Correct 

But,

static class xyz {/*Body of class*/} //Wrong
static structure {/*Body of structure*/} //Wrong

但是对于未命名的名称空间也可以这样。 例如,

 namespace {
           class xyz {/*Body of class*/}
           static structure {/*Body of structure*/}
  } //Correct

匿名命名空间使所包含的变量、函数、类等仅在该文件中可用。在你的例子中,这是一种避免全局变量的方法。运行时或编译时性能没有差异。

除了“我想要这个变量、函数、类等是公共的还是私有的?”之外,没有太多的优点或缺点。

在匿名名称空间中存在某个符号意味着它是这个翻译单元(.cpp文件及其所有包含)的本地符号,这意味着如果在其他地方定义了另一个具有相同名称的符号,则不会违反One Definition Rule (ODR)。

这与C中具有静态全局变量或静态函数的方式相同,但它也可以用于类定义(在c++中应该使用而不是静态)。

同一文件中的所有匿名名称空间都被视为相同的名称空间,不同文件中的所有匿名名称空间是不同的。匿名命名空间相当于:

namespace __unique_compiler_generated_identifer0x42 {
    ...
}
using namespace __unique_compiler_generated_identifer0x42;

除了这个问题的其他答案之外,使用匿名名称空间还可以提高性能。由于名称空间内的符号不需要任何外部链接,因此编译器可以更自由地对名称空间内的代码进行积极优化。例如,在循环中被多次调用的函数可以内联,而不会对代码大小产生任何影响。

例如,在我的系统上,如果使用匿名名称空间,以下代码将占用大约70%的运行时间(x86-64 gcc-4.6.3和-O2;注意,add_val中的额外代码使编译器不想包含它两次)。

#include <iostream>

namespace {
  double a;
  void b(double x)
  {
    a -= x;
  }
  void add_val(double x)
  {
    a += x;
    if(x==0.01) b(0);
    if(x==0.02) b(0.6);
    if(x==0.03) b(-0.1);
    if(x==0.04) b(0.4);
  }
}

int main()
{
  a = 0;
  for(int i=0; i<1000000000; ++i)
    {
      add_val(i*1e-10);
    }
  std::cout << a << '\n';
  return 0;
}