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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/357404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:53:36  来源:igfitidea点击:

Why are unnamed namespaces used and what are their benefits?

c++oopnamespaces

提问by Scottie T

I just joined a new C++ software project and I'm trying to understand the design. The project makes frequent use of unnamed namespaces. For example, something like this may occur in a class definition file:

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

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

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

What are the design considerations that might cause one to use an unnamed namespace? What are the advantages and disadvantages?

哪些设计考虑可能会导致使用未命名的命名空间?有什么优点和缺点?

采纳答案by Johannes Schaub - litb

(In the following, the things are stuff that does not apply anymore to C++11, but did apply to C++03. C++11 makes almost no differences anymore (if there are, they are just language lawyer differences which I can't recall).).

(在下文中,这些东西不再适用于 C++11,但适用于 C++03。C++11 几乎不再有任何区别(如果有,它们只是语言律师的区别,想不起来了))。

Unnamed namespaces are a utility to make an identifier translation unit local. They behave as if you would choose a unique name per translation unit for a namespace:

未命名命名空间是一种使标识符转换单元本地化的实用程序。它们的行为就像您会为命名空间的每个翻译单元选择一个唯一的名称:

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

The extra step using the empty body is important, so you can already refer within the namespace body to identifiers like ::namethat are defined in that namespace, since the using directive already took place.

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

This means you can have free functions called (for example) helpthat can exist in multiple translation units, and they won't clash at link time. The effect is almost identical to using the statickeyword used in C which you can put in in the declaration of identifiers. Unnamed namespaces are a superior alternative, being able to even make a type translation unit local.

这意味着您可以调用(例如)help可以存在于多个翻译单元中的自由函数,并且它们不会在链接时发生冲突。效果几乎与使用staticC 中使用的关键字相同,您可以将其放入标识符声明中。未命名的命名空间是一个更好的选择,甚至可以将类型转换单元设为本地。

namespace { int a1; }
static int a2;

Both a's are translation unit local and won't clash at link time. But the difference is that the a1in the anonymous namespace gets a unique name.

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

Read the excellent article at comeau-computing Why is an unnamed namespace used instead of static?(Archive.org mirror).

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

回答by Motti

Having something in an anonymous namespace means it's local to this translation unit(.cpp file and all its includes) this means that if another symbol with the same name is defined elsewhere there will not be a violation of the One Definition Rule(ODR).

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

This is the same as the C way of having a static global variable or static function but it can be used for class definitions as well (and should be used rather than staticin C++).

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

All anonymous namespaces in the same file are treated as the same namespace and all anonymous namespaces in different files are distinct. An anonymous namespace is the equivalent of:

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

namespace __unique_compiler_generated_identifer0x42 {
    ...
}
using namespace __unique_compiler_generated_identifer0x42;

回答by Sachin

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

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

static int x;  // Correct 

But,

但,

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

But same can be possible with unnamed namespace. For example,

但是对于未命名的命名空间,同样也是可能的。例如,

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

回答by xioxox

In addition to the other answers to this question, using an anonymous namespace can also improve performance. As symbols within the namespace do not need any external linkage, the compiler is freer to perform aggressive optimization of the code within the namespace. For example, a function which is called multiple times once in a loop can be inlined without any impact on the code size.

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

For example, on my system the following code takes around 70% of the run time if the anonymous namespace is used (x86-64 gcc-4.6.3 and -O2; note that the extra code in add_val makes the compiler not want to include it twice).

例如,在我的系统上,如果使用匿名命名空间(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;
}

回答by Marc Mutz - mmutz

The example shows that the people in the project you joined don't understand anonymous namespaces :)

这个例子表明你加入的项目中的人不理解匿名命名空间:)

namespace {
    const int SIZE_OF_ARRAY_X;
    const int SIZE_OF_ARRAY_Y;

These don't need to be in an anonymous namespace, since constobject already have static linkage and therefore can't possibly conflict with identifiers of the same name in another translation unit.

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

    bool getState(userType*,otherUserType*);
}

And this is actually a pessimisation: getState()has external linkage. It is usually better to prefer static linkage, as that doesn't pollute the symbol table. It is better to write

而这其实是一种悲观:getState()有外链。通常最好选择静态链接,因为它不会污染符号表。最好写

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

here. I fell into the same trap (there's wording in the standard that suggest that file-statics are somehow deprecated in favour of anonymous namespaces), but working in a large C++ project like KDE, you get lots of people that turn your head the right way around again :)

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

回答by Max Lybbert

An anonymous namespace makes the enclosed variables, functions, classes, etc. available only inside that file. In your example it's a way to avoid global variables. There is no runtime or compile time performance difference.

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

There isn't so much an advantage or disadvantage aside from "do I want this variable, function, class, etc. to be public or private?"

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