51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1890|回复: 0
打印 上一主题 下一主题

[讨论] 匿名namespace的作用以及它与static的区别

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2008-1-16 10:47:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一。匿名namespace的作用在C语言中,如果我们在多个tu(translation unit)中使用了同一个名字做为函数

名或者全局变量名,则在链接阶段就会发生重定义错误,为了解决这个问题,我们可以在定义这些标识符

(identifier)的时候加上static关键字修饰以限制它只在一个tu范围内可见。C++继承了C语言中static关键字

的这个用途,我们依旧可以使用static来避免多个tu中使用同一个标识符带来的重定义问题。此外C++还提供了另

一种特有的方式,那就是匿名namespace:一个没有指定名字的namespace被称为一个匿名namespace;在一个

tu中可以出现多个匿名namespace,并且相同层次的匿名namespace实际上被合成为同一个;出现在不同tu的匿

名namespace中的相同标识符相互独立不会发生冲突,因此我们可以把那些只希望在同一个tu范围可见的全局标识

符放入一个匿名namespace中,效果与前面加static相同。二。匿名namespace与static的区别一个全局标识符

被static修饰后它的linkage变为internal linkage,这就是为什么不同tu中的相同标识符不会发生冲突的原

因。而匿名namespace却并不会改变在它内部定义的标识符的linkage,它用来避免名字冲突所采用的手段同C++

用来实现重载的手段一摸一样,就是使用名字改编(name mangling):根据C++标准7.3.1.1,每个tu中的匿名

namespace实际上会拥有一个独一无二的名字,因此在不同tu的匿名namespace中相同的标识符实际上属于不同的

namespace,自然在名字改编后就不会发生冲突了:

[quote7.3.1.1 Unnamed namespaces [namespace.unnamed]
An unnamed-namespace-definition behaves as if it were replaced by  
    namespace unique { /* empty body */ }        
    using namespace uniqui;
    namespace unique { namespace-body }
where all occurrences of unique in a translation unit are replacedby the same identifier and this identifier differs from all otheridentifiers in the entire program.end quote]

为什么匿名namespace不采取跟static一样的做法呢,搞个新花样岂不是增加了编译器开发的负担?这其实是因

为另一个C++的特性牵制了匿名namespace的实现,那就是模板非类型参数(template non-type arguments):

[quote14.3.2 Template non-type arguments [temp.arg.nontype]A template-argument for a non-type, non-template template-parametershall be one of:
— an integral constant-expression of integral or enumeration type; or
— the name of a non-type template-parameter; or
— the address of an object or function with external linkage,
including   function templates and function template-ids but excluding
non-static   class members, expressed as & id-expression where the & is
optional   if the name refers to a function or array, or if the corresponding  
template-parameter is a reference; or
— a pointer to member expressed as described in 5.3.1 .end quote]

正是被红字标出的external linkage这一需求限制了匿名namespace的实现!试想一下,假如我们

有一个全局对象或者函数只希望它在一个tu中有效,又希望能够用它的地址来实例化一个模板,怎么办?

只在一个tu中有效,可以选择internal linkage,但是要用它的地址做为模板参数,又要求它必须要是

external linkage!!很显然,匿名namespace不改变其内部标识符的linkage这一性质解决了这一难题,我们

可以把这个全局对象或者函数放心的扔在一个匿名namespace中,然后用它的地址来实例化一个模板,绝对不会发

生重定义错误现在大部分C++书籍都认为匿名namespace和static是相同的,而正如这里所阐述的,它们之间差

异是明显的:static修饰的标识符由于internal linkage的限制,是不能用来实例化模板的!最后给出一个例

子证实匿名namespace确实不改变linkage,呵呵代码中验证了external linkage/internal linkage/no

linkage三种情况

---------------------------------------------------------

template <char *p>

struct foo
{  

void bar();

};

static char a ='a';

namespace

{  char b = 'b';

  static char c = 'c';

  template <class T> struct xxx {};

void foobar()  

{  

  struct no_linkage {};  

  xxx<no_linkage>();  // 如果编译错误,说明no_linkage的linkage没有变化  

}

}

int main()

{  foo<&a>().bar();  // 由于a的linkage是internal,因此应该编译错误  

foo<&b>().bar();  // 如果编译正确,说明b的linkage是external

foo<&c>().bar();  // 如果编译错误,说明c的linkage是internal

foobar();

return 0;

}

---------------------------------------------------------

Comeau C/C++ 4.3.3 (Aug  6 2003 15:13:37) for ONLINE_EVALUATION_BETA1Copyright

1988-2003 Comeau Computing.  All rights reserved.

MODE:strict errors C++

"ComeauTest.c", line 19: error: a template argument may not reference a         

local type      

xxx<no_linkage>();         

^         
^

"ComeauTest.c", line 25: error: a template argument may not reference a         

non-external entity         

Hint: http://www.comeaucomputing.com/techtalk/templates/#stringliteral

foo<&a>().bar();      

^

"ComeauTest.c", line 27: error: a template argument may not reference a         

non-external entity         

Hint: http://www.comeaucomputing.com/techtalk/templates/#stringliteral

foo<&c>().bar();      

^

3 errors detected in the compilation of "ComeauTest.c".

[ 本帖最后由 晓诺 于 2008-1-16 11:39 编辑 ]
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-9 00:42 , Processed in 0.064008 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表