对于那些做过一些c/c ++维护或增强的人来说,未经初始化的本地人所造成的维护问题(尤其是指针)将是显而易见的,但我仍然看到它们并偶尔听到作为其理由的性能影响.
在c中很容易证明冗余初始化已经过优化:
$ less test.c #includemain() { #ifdef INIT_LOC int a = 33; int b; memset(&b,66,sizeof(b)); #else int a; int b; #endif a = 0; b = 0; printf ("a = %i, b = %i\n", a, b); } $ gcc --version gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
[未优化:]
$ gcc test.c -S -o no_init.s; gcc test.c -S -D INIT_LOC=1 -o init.s; diff no_in it.s init.s 22a23,28 > movl $33, -4(%ebp) > movl $4, 8(%esp) > movl $66, 4(%esp) > leal -8(%ebp), %eax > movl %eax, (%esp) > call _memset 33a40 > .def _memset; .scl 3; .type 32; .endef
[优化:]
$ gcc test.c -O -S -o no_init.s; gcc test.c -O -S -D INIT_LOC=1 -o init.s; diff no_init.s init.s $
那么在什么情况下WRT性能是强制变量初始化不是一个好主意?
如果适用,不需要限制c/c ++的答案,但请明确语言/环境(和可重复的证据比推测更受欢迎!)
简短回答:声明变量尽可能接近第一次使用,如果仍需要则初始化为"零".
答案很长:如果在函数开头声明变量,并且在以后不使用它,则应该重新考虑变量的位置作为本地范围.然后,您通常可以立即为其分配所需的值.
如果必须声明它未初始化,因为它是在条件中分配的,或者通过引用传递并分配给它,将它初始化为null等效值是一个好主意.如果您在-Wall下编译,编译器有时可以保存您,因为如果您在初始化之前读取变量,它将发出警告.但是,如果将其传递给函数,则无法向您发出警告.
如果您安全地将其设置为null等效,那么如果您传递它的函数会覆盖它,则不会造成任何伤害.但是,如果你传递给它的函数使用了这个值,你几乎可以保证失败一个断言(如果你有一个),或者至少在第二个断言你使用一个空对象.随机初始化可以做各种不好的事情,包括"工作".
如果您认为初始化是多余的,那就是.我的目标是编写尽可能人性化的代码.不必要的初始化会使未来的读者感到困惑.
C编译器在捕获单元化变量的使用方面相当擅长,因此现在的危险性很小.
不要忘记,通过"假"初始化,你交易一个危险 - 崩溃使用垃圾(这导致一个很容易找到和修复的错误)在另一个 - 程序采取基于假值的错误行动(导致一个很难找到的bug).选择取决于应用程序.对某些人来说,永远不会崩溃至关重要.对于大多数人来说,最好尽快捕获错误.
这是一个很好的例子,过早优化是万恶之源
完整的报价是:
毫无疑问,效率的严重性会导致滥用.程序员浪费了大量时间来思考或担心程序中非关键部分的速度,而这些效率尝试实际上在考虑调试和维护时会产生很大的负面影响.我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源. 然而,我们不应该放弃那个关键的3%的机会.一个优秀的程序员不会因为这样的推理而自满,他会明智地仔细研究关键代码; 但只有在确定了该代码之后.
这来自唐纳德克努特.你会相信谁...你的同事还是Knuth?
我知道我的钱在哪里......
回到最初的问题:"我们应该进行MANDATE初始化吗?"
我会这样说:
变量应该初始化,除非可以证明通过不初始化可以实现显着的性能增益.来自硬数字...