使用可变值初始化静态文件需要多少运行时成本? 在C++中,在一个合理的编译器中初始化一个静态变量的预期运行时开销是什么,而不是一个常量值? 例如,考虑这个代码: bool foo(); bool baz1() { const bool value = foo(); static bool alternate1 = value; static bool alternate2 = false; // Do something. return alternate1; }
使用可变值初始化静态文件需要多少运行时成本? 在C++中,在一个合理的编译器中初始化一个静态变量的预期运行时开销是什么,而不是一个常量值? 例如,考虑这个代码: bool foo(); bool baz1() { const bool value = foo(); static bool alternate1 = value; static bool alternate2 = false; // Do something. return alternate1; },c++,static,initialization,runtime,C++,Static,Initialization,Runtime,alternate1和alternate2之间的预期运行时成本差异是多少?静态变量在程序开始时初始化,这意味着初始化只会发生一次。仅仅一个布尔值的成本非常低,而对于您的alternate1将是执行foo()的成本,在您的示例中这并不多,因为它只是一个空函数 一般来说,成本将是初始化基本类型(int、float等)或初始化任何用户定义类型/库定义类型(运行ctor)的最大成本。任何使用函数初始化的静态,则最大值将是正在执行的函数的成本 编译时常量(备选2)的初始化最有可能发生在程序启动期间,每次调
alternate1
和alternate2
之间的预期运行时成本差异是多少?静态变量在程序开始时初始化,这意味着初始化只会发生一次。仅仅一个布尔值的成本非常低,而对于您的alternate1
将是执行foo()
的成本,在您的示例中这并不多,因为它只是一个空函数
一般来说,成本将是初始化基本类型(int、float等)或初始化任何用户定义类型/库定义类型(运行ctor)的最大成本。任何使用函数初始化的静态
,则最大值将是正在执行的函数的成本 编译时常量(备选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生成的代码的观察。设置alternate1
值意味着调用函数,即使函数返回静态值,也必须保存堆栈、调用函数、获取其返回值、恢复堆栈并将值赋给变量
从字面上看,在第一种情况下,您将执行至少8个汇编代码行,而在第二种情况下,您将只执行一行。您的问题似乎不是关于一般的静态变量,而是关于函数中声明的静态变量
从运行时值初始化此类变量的额外运行时成本来自多个来源
当控件第一次(如果有的话)通过其声明时,此类变量只应初始化一次。为了实现为每个这样的变量分配一个额外的布尔变量/标志,并在每次控件通过声明时进行检查。如果该标志表示变量尚未初始化,则该变量将被初始化
对于那些静态变量具有非平凡的析构函数,语言必须保证它们在程序终止时的销毁顺序与其构造顺序相反。由于施工顺序在运行时确定,因此程序必须准备运行时结构,以安排未来的破坏。对于具有非平凡析构函数的变量,这也是步骤1的一部分:它们按照构造顺序注册在构造对象的“列表”中。“列表”通常实现为预先分配的数组(因为其最大大小在编译时已知)
在多线程配置中,上述步骤可能/将伴随其他锁定/解锁步骤
由于这些都是“暗中”实施的“家庭”开支,实际成本可能在很大程度上取决于实施情况。查看/分析特定编译器生成的代码。这真的是性能瓶颈吗?函数中声明的静态变量在控件第一次到达它们时进行初始化,并且初始化必须是线程安全的,因此这会带来一些成本。初始化部分不是用词不当吗?它与编译后的程序一起存储,对吗?实际上,函数中声明的静态变量至少在控件第一次到达它们时被初始化。例如,如果编译器是常量,则允许它在启动时初始化。我确实需要始终调用foo()。如果编译器可以在编译时知道它的值并对其进行优化,则不需要调用其他函数。此外,在我看来,如果不讨论优化(包括LTO)、CPU、CISC与RISC等之间的差异,就可以量化每种情况下需要多少“汇编代码行”的想法似乎是荒谬的。这不是一件普遍的事情。