unnamed namespace和static关键字

1. 一份代码转变成可执行文件需要经过以下几个步骤:

 

一开始,预编译器进行代码转换(宏定义等),生成translation unit,然后编译器将多个translation unit转换为汇编指令,汇编指令进一步变成可被计算机识别的机器码,最终在链接阶段,将机器码与操作系统结合生成可执行文件。详细的编译过程请参考:http://www.cs.cf.ac.uk/Dave/C/node3.htmlhttp://www.tenouk.com/ModuleW.html


      内部链接(Internal linkage): identifiers can only be seen within a translation unit.标识符只能被一个编译单元访问。

     外部链接 (External linkage):identifiers can be seen (and referred to) in other translation units.标识符可以被其它的编译 单元访问或引用。

     无连接(No linkage): identifiers can only be seen in the scope in which they are defined.标识符只能在它们定义的范围内访问。

    编译单元(translation unit):是编译阶段的入口,同时也是预处理阶段的出口,编译阶段通过对编译单元的处理产生obj文件。编译单元通常包括一个源文件、源文件内直接或间接引用的头文件,减去条件预处理语句忽略的部分。

      在c++03标准中(c++真正正式公布的标准有c++98 c++03 c++11),内部链接的标识符不能作为template 参数,因此在unnamed namespace内的标识符拥有外部链接的属性,目的是能够被模板使用。但是,你可以在通过在unnamed namespace内部的标识符前添加关键字static实现标识符内部链接的属性,这和named namespaceglobal namespace效果是一样的。

    但是在c++11标准中,内部链接也可以作为模板的参数了,同时,缺省情况下,在unnamed namespace内部的标识符也变成了内部链接。

    c++03 标准:3.5 Program and linkage.

    c++11 标准:

     An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage.A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of

                ----a variable; or

               -----a function; or

               -----a named class (Clause 9), or an unnamed class in a typedef declaration in which the class has the typedef name for linkage purpose; or

               -----a named enumeration, or an unnamed enumeration defined in a typedef declaration in which the enumerator has the typedef name for linkage purpose; or

               -----a enumerator belonging to an enumeration with linkage; or

              ------a template.

什么是Global namespace?

c++11标准给出的定义:

The outermost declarative region of a translation unit is also a namespace, called the global namespace. A name declared in the global namespace has global namespace scope(also called global scope). the potential scope of such a name begins at its point of declaration and ends at the end of translation unit that is its declarative region. Names with global namespace scope are said to global.

简单点讲就是全局变量。

// testPro1.cpp : 定义控制台应用程序的入口点。
#include <string>
#include <iostream>
int g_test;
static int g_tStatic = 10; 
int main(int argc, char* argv[])
{
	g_test = 5;
	::g_test = 5;
        ::g_tStatic = 13;
        g_tStatic = 13;
        system("pause");
	return 0;
}

通常情况下我们的写法是直接调用,也可以采用在name前面添加作用域限定符(::)的方式调用。

下面进入正题,为什么c++推荐使用unnamed namespace 来代替static?

在c语言中,static有一个重要的作用就是限定标识符的作用域,也可以称为信息隐藏,在一个文件内定义的变量或者函数前添加了static关键字,就将该变量或函数的作用域限定在该函数内,对应于internal linkage。

c++为了兼容c语言,保留了static的这一功能,同时提供了一个可以替换的版本,也就是unnamed namespace,并且在标准中推荐使用unnamed namespace来代替static。

在c++11中,7.3.1.1 Unnamed namespaces这一小节,讲了在编译器对unamed namespace做的进一步处理。

在编译阶段,编译器对每个unnamed namespace产生了一个唯一的名称,因此,在每一个编译单元内,unnamed namespace内的标识符都不能被其它编译单元看到。eg,flag在有internal linkage,它全名应该视unique::flag,但是由于unique仅在文件x.cpp内有效,因此flag的有效范围也就是x.cpp,其它的编译单元并不知道它的存在。

c++推荐使用unnamed namespace代替static的可能原因:

1. 在c++中未来的趋势可能就是用unnamed namespace来代替staic实现作用域限定。

2. static无法作用于class、template、enum、namespace等。当你想要对一个类、者枚举、模板或者另一个命名空间实现作用域限定时,就必须求助于 unnamed namespace了。

3.template的参数不能为internal linkage,但是虽然c++11标准规定unnamed namespace内的标识符均为internal linkage,但是却允许作为template的参数,原因可能就是编译阶段为其生成了一个唯一的name。

eg.

int g_test;
static int g_tstatic;
namespace{
int t_ff =0;
}

template <const int& T> struct g_tm { };
g_tm<g_test> y; //ok
g_tm<t_ff> tt; //ok
g_tm<g_tstatic> y2; //not ok
template <char* T> struct g_tc;
void fun()
{
	char t_buf[] = "local";
 	g_tc<t_buf> t_tb;//not ok
 	static char t_buf2[] = "local";
 	g_tc<t_buf2> t_tb2;//not ok
}

参考文献:

1. http://www.comeaucomputing.com/techtalk/#nostatic

2. c++标准c++11 C++03

3. http://www.cplusplus.com/doc/tutorial/templates/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值