unnamed namespace
- 匿名命名空间可以在给定的文件中不连续,但不能跨越多个文件。
- 匿名的命名空间用于声明局部于文件的实体,在匿名的命名空间中定义的变量在程序开始时创建,在程序结束时一直存在。
- 匿名的命名空间中定义的名字可直接使用,没有完全限定名。
- 匿名的命名空间中定义的名字只在本文件中可见。
- 匿名的命名空间中定义的名字可以在定义该命名空间所在的作用域中可见,如果在文件的最外层作用域中定义匿名的命名空间,那么该匿名的命名空间中的名字必须与全局作用域中的名字不同。
通常除了类的静态成员函数和静态数据成员外,其它的static需求都提倡使用匿名命名空间来代替。
1.代替static用法
在标准C中,如果期望一个变量或者一种函数只能被本源文件(同个translation unit)使用,通常的做法是使用static来修饰这个变量/函数,来保证这个变量/函数具有内部链接(internal linkage)。这种技术称为信息隐藏。
在C++中,仍然支持这种做法,但是已经不提倡,C++只提倡static仅仅用于修饰类成员,不再提倡用static来修饰非类成员。在以后的编译器中,可能会对使用static来修饰非类成员的方式给出编译警告。
2.不要在.h文件中使用匿名命名空间
提倡在cpp/c源文件中使用unnamed namespace,不要(不提倡)在.h文件中使用匿名命令空间,因为其将生成大量不被使用类型或者数据—这些数据不是副本,是全局唯一的(原因见下面)。
这里重提一下:.h文件与.cpp文件。.h文件不是编译单元,所以不能直接编译.h文件;.cpp/.cc文件才是编译单元,编译器可以直接编译.cpp/.cc文件。那么如果一个.cpp文件include了.h文件,是什么效果呢?直白的意思就是:把所有(直接/间接)include的.h的文件内容直接复制到该.cpp文件中,再对该.cpp文件编译。这就意味着,如果在一个头文件中定义了unnamed namespace,那么所有include该.h的编译单元(.cpp/.cc文件),都会完全包含该.h文件中的所有内容,那么,一个.cpp/.cc中包含的匿名空间里的数据,它自己当然能访问了。无论它具有的是内部链接属性,还是外部链接属性,都不影响访问。(除非对访问对象有链接属性要求的场景:比如模块的非类型参数-数据实参)。
3.在模板元设计中小心使用匿名命名空间
匿名空间具有内部链接属性,其内部定义的函数/类型/变量/常量在不同的编译单元都是不同的,所以在进行模板设计时,尤其要小心,以防止传入的类型参数来自于不同编译单元的匿名命名空间,这样开发者字面意思看到的是同一类型,但是模板元逻辑处理中,竟然是不同的类型,很容易被认为是编译器的bug。
出于这个目的,我们可以考虑在模板元设计中禁止使用匿名命名空间。
这其实是上一条规则中的一个实例:因为模板元代码都是在.h文件中的,而”不要在.h文件中使用匿名命名空间”。
- Post link: https://github.com/TheBge/TheBge.github.io/2020/12/02/%E5%8C%BF%E5%90%8D%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub IssuesGitHub Discussions