[英]What run-time costs are there to initializing a static with a variable value?
在C ++中,用合理的编译器初始化带有变量值而不是常量值的静态变量的预期运行时间是多少?
例如,考虑以下代码:
bool foo();
bool baz1() {
const bool value = foo();
static bool alternate1 = value;
static bool alternate2 = false;
// Do something.
return alternate1;
}
alternate1
和alternate2
之间的预期运行时成本差异是多少?
从编译时常量(替代2)进行初始化很可能会在程序启动期间发生,每次调用该函数都不会产生成本。
局部静态变量的线程安全初始化将导致编译器生成类似以下伪代码的内容:
static bool alternate1;
static bool __initialised = false;
static __lock_type __lock;
if (!__initialised) {
acquire(__lock);
if (!__initialised) {
alternate1 = value;
__initialised = true;
}
release(__lock);
}
因此,每次调用该函数(可能涉及内存屏障或其他同步原语)时,都有可能对标志进行测试,并且首次获取和释放锁会产生进一步的开销。
请注意,在代码中,无论变量是否已初始化,每次都会调用foo()
。 如果您将初始化更改为
static bool alternate1 = foo();
当然,细节取决于实现。 这是基于我对GCC生成的代码的观察。
static
变量在程序开始时进行初始化,这意味着初始化只会发生一次。 仅一个布尔值的成本就非常低,而对于alternate1
将是执行foo()
的成本,在您的示例中这并不算多,因为它只是一个空函数。
概括地说,成本将是初始化基本类型(int,float等)或任何用户定义类型/库定义类型的初始化(运行ctor)的最大成本。 用函数初始化的任何static
,则最大值将是函数执行的成本。
看来,您的问题通常与静态变量无关,而与在函数内部声明的静态变量有关。
从运行时值初始化此类变量的额外运行时成本来自多个来源
当控件第一次超过其声明时(如果有的话),此类变量应仅初始化一次。 为了实现为每个此类变量分配一个附加的布尔变量/标志,并在每次控件通过声明时进行检查。 如果标志指示变量尚未初始化,则将其初始化。
对于那些具有非平凡析构函数的静态变量,该语言必须保证在程序终止时其销毁顺序与它们的构造顺序相反。 由于施工顺序是在运行时确定的,因此程序必须准备一个运行时结构以计划将来的破坏。 对于具有非平凡析构函数的变量,这也作为步骤1的一部分完成:按构造顺序将它们注册在构造对象的“列表”中。 “列表”通常实现为预分配的数组(因为在编译时已知其最大大小)。
在多线程配置中,上述步骤可能会/将伴随其他锁定/解锁步骤。
由于这些都是在“幕后”实施的“家庭”支出,因此实际成本可能在很大程度上取决于实施。 查看/分析您的特定编译器生成的代码。
设置alternate1
值将意味着调用该函数,即使该函数返回静态值,也将必须保存堆栈,调用该函数,获取其返回值,还原堆栈并将该值分配给变量。
从字面上看,在第一种情况下,您将执行至少8条汇编代码行,而在第二种情况下,将仅执行一行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.