这是一个单例,因为static
本地函数的存储持续时间意味着程序中仅存在该本地函数的一个实例。
在底层,这可以非常粗略地被认为等同于以下 C++98(甚至可能由编译器像这样模糊地实现):
static bool __guard = false;
static char __storage[sizeof(Singleton)]; // also align it
Singleton& Instance() {
if (!__guard ) {
__guard = true;
new (__storage) Singleton();
}
return *reinterpret_cast<Singleton*>(__storage);
}
// called automatically when the process exits
void __destruct() {
if (__guard)
reinterpret_cast<Singleton*>(__storage)->~Singleton();
}
线程安全位使它变得有点复杂,但本质上是一样的。
看看 C++11 的实际实现,有一个保护变量对于每个静态(如上面的布尔值),它也用于屏障和线程。查看 Clang 的 AMD64 输出:
Singleton& instance() {
static Singleton instance;
return instance;
}
AMD64 程序集instance
来自 AMD64 上的 Ubuntu 的 Clang 3.0,位于 -O1(由http://gcc.godbolt.org/ http://gcc.godbolt.org/ is:
instance(): # @instance()
pushq %rbp
movq %rsp, %rbp
movb guard variable for instance()::instance(%rip), %al
testb %al, %al
jne .LBB0_3
movl guard variable for instance()::instance, %edi
callq __cxa_guard_acquire
testl %eax, %eax
je .LBB0_3
movl instance()::instance, %edi
callq Singleton::Singleton()
movl guard variable for instance()::instance, %edi
callq __cxa_guard_release
.LBB0_3:
movl instance()::instance, %eax
popq %rbp
ret
可以看到它引用了一个全局守卫来查看是否需要初始化,使用__cxa_guard_acquire
,再次测试初始化,依此类推。几乎在所有方面都与您从维基百科发布的版本完全相同,除了使用 AMD64 程序集和中指定的符号/布局安腾ABI http://refspecs.linux-foundation.org/cxxabi-1.83.html#guards.
请注意,如果您运行该测试,您应该给出Singleton
一个不平凡的构造函数,因此它不是一个 POD,否则优化器将意识到没有必要执行所有这些保护/锁定工作。