
如下代码,第一次调用 fn 时会执行 get_value ,后续调用不会执行:
void fn() { static int x = get_value(); // ... } 如果代码里显示调用该函数,编译器可能会优化,在第一次调用前初始化。
但如果通过函数指针动态调用,或者将该函数对外导出,那么每次调用 fn 时是否都要判断一下有没有初始化?
1 BingoXuan 2023 年 7 月 17 日 op 的例子编译出错,initializer element is not constant 。 不如改成 static int x; static int is_initialized = 0; if (!is_initialized) { x = get_value(); is_initialized = 1; } |
2 Inn0Vat10n 2023 年 7 月 17 日 每次调用 fn 都有额外开销的,比较常见的场景是用这种方式实现的单例模式 ?t=1143 |
3 tool2d 2023 年 7 月 17 日 @BingoXuan 我看 VC 反编译汇编代码,编译器有自动包含 is_initialized ,就在 static int x 内存地址的前面。 如果调用了 get_value 后,这个匿名地址( u8 )会被赋值为 1 ,证明这个 x 已经被初始化过一次了。 每次 fn 进入后,都会先判断这个地址是 0 (变量未初始化),还是 1 (已初始化) |
4 codehz 2023 年 7 月 17 日 |
5 lakehylia 2023 年 7 月 17 日 @codehz Starting in C++11, a static local variable initialization is guaranteed to be thread-safe |
6 Shatyuka 2023 年 7 月 17 日 “如果代码里显示调用该函数,编译器可能会优化,在第一次调用前初始化。” 举个例子?初始化成常量? 8.8.4:Dynamic initialization of a block-scope variable with static storage duration (6.7.5.1) or thread storage duration (6.7.5.2) is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. |
7 mogg 2023 年 7 月 17 日 1. static 对象的存储在程序开始时分配,并在程序结束时解分配 2. 控制流首次经过变量声明时才会被初始化,之后所有调用都会跳过 3. c++的话,c++11 之前这样不是线程安全的(即多个线程试图同时初始化),c++11 之后线程安全。c 的话不太确定 4. 不确定你的“零开销” 是什么含义,c++里如果你的 get_value 是 consteval 的,会在编译期执行完,但是 c 里吗应该是在运行时执行一次 |