与其他一些语言不同,C++ 允许静态数据为任意类型,而不仅仅是普通的旧数据。简单的旧数据初始化很简单(编译器只是将值写入数据段中的适当地址),但其他更复杂的类型则不然。
非 POD 类型的初始化通常如何在 C++ 中实现?特别是,foo第一次执行该函数时究竟发生了什么?使用什么机制来跟踪是否str已经初始化?
#include <string>
void foo() {
static std::string str("Hello, Stack Overflow!");
}
Run Code Online (Sandbox Code Playgroud)
C++11 要求函数局部static变量的初始化是线程安全的。因此,至少在兼容的编译器中,通常会使用某种同步原语,每次输入函数时都需要检查这些原语。
#include <string>
void foo() {
static std::string str("Hello, Stack Overflow!");
}
int main() {}
Run Code Online (Sandbox Code Playgroud)
.LC0:
.string "Hello, Stack Overflow!"
foo():
cmpb $0, guard variable for foo()::str(%rip)
je .L14
ret
.L14:
pushq %rbx
movl guard variable for foo()::str, %edi
subq $16, %rsp
call __cxa_guard_acquire
testl %eax, %eax
jne .L15
.L1:
addq $16, %rsp
popq %rbx
ret
.L15:
leaq 15(%rsp), %rdx
movl $.LC0, %esi
movl foo()::str, %edi
call std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
movl guard variable for foo()::str, %edi
call __cxa_guard_release
movl $__dso_handle, %edx
movl foo()::str, %esi
movl std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string(), %edi
call __cxa_atexit
jmp .L1
movq %rax, %rbx
movl guard variable for foo()::str, %edi
call __cxa_guard_abort
movq %rbx, %rdi
call _Unwind_Resume
main:
xorl %eax, %eax
ret
Run Code Online (Sandbox Code Playgroud)
的__cxa_guard_acquire,__cxa_guard_release等守卫静态变量的初始化。