当前位置:  开发笔记 > 编程语言 > 正文

为什么使用未命名的命名空间以及它们有什么好处?

如何解决《为什么使用未命名的命名空间以及它们有什么好处?》经验,为你挑选了6个好方法。

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

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

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

可能导致使用未命名的命名空间的设计注意事项是什么?有哪些优点和缺点?



1> Johannes Sch..:

(在下文中,引人注目的东西不再适用于C++ 11,但确实适用于C++ 03.C ++ 11几乎没有任何差异(如果有的话,它们只是语言)我不记得的律师差异).

未命名的命名空间是一个实用程序,用于使标识符有效地转换单元本地.它们的行为就像为命名空间选择每个翻译单元的唯一名称一样:

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

使用空体的额外步骤很重要,因此您可以在命名空间体内引用类似于::name该命名空间中定义的标识符,因为using指令已经发生.

这意味着您可以拥有help可以存在于多个翻译单元中的自由函数(例如),并且它们不会在链接时发生冲突,因为它们都具有唯一的名称,因为它们具有唯一的名称空间.效果几乎与使用staticC中使用的关键字相同,您可以将其放入标识符声明中.a以这种方式使用的方法在C++中已弃用,因为未命名的命名空间是一种更好的选择,甚至可以使类型转换单元本地化.

namespace { int a1; }
static int a2;

两者a1都是本地翻译单位,不会在链接时发生冲突.但不同之处在于::name匿名命名空间中只有一个唯一的名称.它仍然具有外部链接,可以导出到正在创建的目标文件的符号表中.如果要将其地址用作模板参数,这一点很重要:

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

模板参数必须具有外部链接,因此在这种情况下,必须将标识符放入匿名命名空间.

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


由于这个答案有很多划掉的陈述而且令人困惑,因此被低估了.很难理解为第一次看到空命名空间的人(c ++初学者)所写的内容的含义.
它真的"还有外部联系"吗?3.5/4似乎暗示匿名命名空间中的所有内容都有内部链接......?
@kerr我的答案已经过时了.我需要为c ++ 11更新它.谢谢

2> Motti..:

在匿名命名空间中有一些东西意味着它是本翻译单元的本地(.cpp文件及其所有包含)这意味着如果在别处定义了具有相同名称的另一个符号,则不会违反一个定义规则(ODR).

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

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

namespace __unique_compiler_generated_identifer0x42 {
    ...
}
using namespace __unique_compiler_generated_identifer0x42;



3> Marc Mutz - ..:

该示例显示您加入的项目中的人员不了解匿名命名空间:)

namespace {
    const int SIZE_OF_ARRAY_X;
    const int SIZE_OF_ARRAY_Y;

这些不需要位于匿名名称空间中,因为const对象已经具有静态链接,因此不可能与另一个翻译单元中的同名标识符冲突.

    bool getState(userType*,otherUserType*);
}

而这实际上是一种悲观情绪:getState()有外部联系.通常更喜欢静态链接,因为它不会污染符号表.写得更好

static bool getState(/*...*/);

这里.我陷入了同样的陷阱(标准中的措辞表明文件静态以某种方式被弃用以支持匿名命名空间),但是在像KDE这样的大型C++项目中工作,你会让很多人以正确的方式转过头来再来一次:)


"这些不需要在匿名命名空间中"从技术上来说,确定 - 但是,把它们放在一起并没有什么坏处,作为对它们语义的视觉提醒,并使它(甚至更多)微不足道地删除它们.如果需要,以后再见.我怀疑这意味着OP的团队"不理解"任何东西!此外,关于具有外部链接的匿名命名空间中的函数的位在C++ 11中是错误的,如上所述.根据我的理解,他们修复了以前需要外部链接的模板参数问题,因此可以允许未命名的命名空间(能够包含模板参数)具有内部链接.
由于c ++ 11未命名的命名空间具有内部链接(标准中的第3.5节或http://en.cppreference.com/w/cpp/language/namespace#Unnamed_namespaces)

4> xioxox..:

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

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

#include 

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;
}


真是太好了 - 我在gcc 4-1-2上尝试了这个段,使用O3优化,带有和没有命名空间语句: - >得到相同的时间(3秒,带-O3,带有-O3的4秒)
@Daniel:我错过了什么?如你所读,你说你把`-O3`比作自己,然后你说3 vs 4秒是"同一时间".这些都没有任何意义.我怀疑_real_解释会,但它是什么?
这个代码故意很复杂,试图说服编译器不要内联b和add_val到main.无论代码膨胀成本如何,O3优化都使用大量内联.但是,仍然存在O3不会内联add_val的函数.您可以尝试使add_val更复杂,或者在不同情况下从main调用多次.

5> Max Lybbert..:

匿名命名空间使得封闭的变量,函数,类等仅在该文件中可用.在您的示例中,它是一种避免全局变量的方法.没有运行时或编译时性能差异.

除了"我希望这个变量,功能,类等是公共的还是私人的?"之外,没有太多优点或缺点.


可能存在性能差异 - 请参阅我的答案.它允许编译器更好地优化代码.
你有一定道理; 至少就今天的C++而言.但是,C++ 98/C++ 03要求事物具有外部链接才能用作模板参数.由于匿名命名空间中的内容可用作模板参数,因此它们将具有外部链接(至少在前C++ 11中),即使无法从文件外部引用它们也是如此.我认为可能有一些能够捏造它的能力,因为标准只要求事情就像规则被执行一样; 并且有时可以在不真正执行规则的情况下这样做.

6> 小智..:

未命名的命名空间将类,变量,函数和对象的访问限制为定义它的文件.未命名的命名空间功能类似于staticC/C++中的关键字.
static关键字限制全局变量和函数对定义它们的文件的访问.
未命名的命名空间和static关键字之间存在差异,因为未命名的命名空间优于静态命名空间.statickeyword可以与变量,函数和对象一起使用,但不能与用户定义的类一起使用.
例如:

static int x;  // Correct 

但,

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

推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有