- 浏览: 202754 次
- 性别:
- 来自: 重庆
文章分类
最新评论
匿名namespace的作用以及它与static的区别
- 博客分类:
- c++
一。匿名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,自然在名字改编后就不会发生冲突了:
[quote
7.3.1.1 Unnamed namespaces [namespace.unnamed]
An unnamed-namespace-definition behaves as if it were replaced by
namespace unique { }
using namespace unique;
namespace unique { namespace-body }
where all occurrences of unique in a translation unit are replaced
by the same identifier and this identifier differs from all other
identifiers in the entire program.
end quote]
为什么匿名namespace不采取跟static一样的做法呢,搞个新花 样岂不是增加
了编译器开发的负担?这其实是因为另一个C++的特性牵制了匿名namespace的
实现,那就是模板非类型参数 (template non-type arguments):
[quote
14.3.2 Template non-type arguments [temp.arg.nontype]
A template-argument for a non-type, non-template template-parameter
shall 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;
}
匿名 namespace 的不利之处
在工程实践中,匿名 namespace 有两大不利之处:
其中的函数难以设断点,如果你像我一样使用的是 gdb 这样的文本模式 debugger。
使用某些版本的 g++ 时,同一个文件每次编译出来的二进制文件会变化,这让某些 build tool 失灵。
发表评论
-
C++的原子操作
2012-12-20 17:43 4658在多进程(线程)访问资源时,能够确保所有其他的进程(线程 ... -
C++类型萃取技术
2012-12-19 15:16 1117Traits技术可以用来获得一个 类型 的相关信息的。 ... -
数值压缩存储方法Varint
2012-12-19 14:35 817转自:http://www.cnblogs.com/smark ... -
TypeList
2012-12-19 13:49 1120转自:http://blog.csdn.n ... -
template <unsigned int N>
2012-12-19 11:51 1466详见:http://stackoverflow.com/ ... -
二维指针*(void **)的研究(uC/OS-II案例)
2012-12-19 22:20 3259原文 : http://blog.csdn ... -
多级指针和链表
2012-12-18 22:28 0如果看到一个声明:t ... -
理解*(void**)b
2012-12-18 22:03 0#include <stdio.h> ... -
STL标准库:Allocator能做什么
2012-12-18 20:10 0The Standard Librarian: Wha ... -
三种的allocator实现源代码的对比
2012-12-18 19:55 1286转自:http://blog.csdn.net ... -
结构体内变量相对便宜与list_entry()宏
2012-12-18 17:59 906#define list_entry(ptr, t ... -
声明与函数、函数指针---(*(void (*)( ) )0)( ) 解析
2012-12-18 17:33 1083概述 在很 ... -
c++模板(类型依赖)说明例子
2012-12-18 16:57 1131#include <iostream> # ... -
C++中三种new的用法
2012-12-18 16:44 1816我评价自己的C++水平还未入门的确不够准确,应该是远远未 ... -
C++,永久改变你写异常安全代码的方式(神奇的Loki::ScopeGuard)
2012-12-17 20:19 2483作者:Andrei Alexandrescu and P ... -
C++的make_pair函数
2012-12-17 17:19 3436Pairs C++标准程序库中凡是“必须返回两 ... -
C++的explicit构造函数
2012-12-13 15:59 627按照默认规定,只有一个参数的构造函数也定义了一个隐式转换 ...
相关推荐
本例主要解释了为什么不用using namespace std;,因为如果这么使用了,在其它地方如果用到了标准库中的标识符(那么多标识符,不能保证都记住),就会报错,如果程序工程很复杂,可能会查找冲突很麻烦,因此在实际...
static关键字是C, C++中都存在的关键字, 它主要有三种使用方式, 其中前两种只指在C语言中使用, 第三种在C++中使用(C,C++中具体细微操作不尽相同, 本文以C++为准). (1)局部静态变量 (2)外部静态变量/函数 (3)静态...
前端开源库-koa-static-namespace.zip
using namespace是使用命名空间 C++
Namespace 命名空间Namespace 命名空间Namespace 命名空间Namespace 命名空间Namespace 命名空间
关于QT中用到的namespace的解释,看完这篇解释,相信你会对QT中为什么多处用到namespace能有较深入的理解!
C++中 namespace介绍 非常有用的东西
autoload与 namespace 实例 学习 理解 帮助学习与理解
C++ namespace 使用方法:把位于不同.cpp文件的变量打包在一个namespace下,在主函数中使用Namespace里面定义的变量。 使用方法:把下载的压缩文件解压到一个目录下
前端开源库-koa-static-namespacekoa静态名称空间,为koa提供中间件的静态文件
主要是讲的作用域,namespace,生命周期,生成期
深入剖析c/c++ namespace!变量作用域,紧紧适合初学着,有源码,有word文档!
visual c++ namespace命名空间 用法
namespace与沙箱安全-explorer,Linux内核的六种Namespace
前端开源库-solid-namespace实体命名空间,实体项目中使用的公共RDF命名空间的集合
演示MS Namespace Shell Extension 创建虚拟目录和次目录的实作范例, 并且增加了新增次目录或档案与删除次目录或档案的演示
JAXB Demo及namespace的prefix自定义解决方案
VC++标准库函数,可以加载 免安装版的sing namespace std;//C++ 标准库函数,
Docker底层服务之NameSpace、Cgroup、存储、网络Docker底层服务之NameSpace、Cgroup、存储、网络Docker底层服务之NameSpace、Cgroup、存储、网络Docker底层服务之NameSpace、Cgroup、存储、网络Docker底层服务之...
namespace命名空间是C++中一个非常重要的概念,...(5) 未命名的namespace:其作用域为定义该namespace所在的声明区域。C++推荐用来替代static定义静态变量。 具体程序代码如下: #include using namespace std; nam