C++ 初始化C+中的数组+;
我看到的每一个地方都有人大声争辩说未初始化的变量是不好的,我当然同意并理解为什么——然而;我的问题是,你有没有不想这样做的时候 例如,以代码为例:C++ 初始化C+中的数组+;,c++,c,performance,arrays,C++,C,Performance,Arrays,我看到的每一个地方都有人大声争辩说未初始化的变量是不好的,我当然同意并理解为什么——然而;我的问题是,你有没有不想这样做的时候 例如,以代码为例: char arrBuffer[1024] = { '\0' }; 在不初始化阵列的情况下,将整个阵列置零是否会对使用阵列的性能产生影响 为什么您关心性能优势,不初始化它会获得多大的性能,以及它是否比垃圾指针在调试过程中节省的时间多。规则是在使用变量之前应该设置它们 如果您知道在使用之前将在其他地方设置它们,则不必在创建时显式初始化它们 例如,以下代
char arrBuffer[1024] = { '\0' };
在不初始化阵列的情况下,将整个阵列置零是否会对使用阵列的性能产生影响 为什么您关心性能优势,不初始化它会获得多大的性能,以及它是否比垃圾指针在调试过程中节省的时间多。规则是在使用变量之前应该设置它们 如果您知道在使用之前将在其他地方设置它们,则不必在创建时显式初始化它们 例如,以下代码完全可以:
int main (void) {
int a[1000];
: :
for (int i =0; i < sizeof(a)/sizeof(*a); i++)
a[i] = i;
: :
// Now use a[whatever] here.
: :
return 0;
}
将导致x[]具有不确定的值。但由于:
void x(void) {
int x[1000] = {0};
}
可能只会导致1000整数memcpy类型的操作(在这种情况下更可能是memset),这也可能很快。您只需记住,每次调用该函数时都会进行初始化。对于大型阵列,性能影响可能非常大。默认情况下初始化所有变量实际上并没有带来很多好处。这并不是一个坏代码的解决方案,而且它可能隐藏实际问题,否则编译器可能会发现这些问题。您需要跟踪所有变量在其整个生命周期中的状态,以使您的代码始终可靠。Measure
#include <stdio.h>
#include <time.h>
int main(void) {
clock_t t0;
int k;
t0 = clock();
for (k=0; k<1000000; k++) {
int a[1000];
a[420] = 420;
}
printf("Without init: %f secs\n", (double)(clock() - t0) / CLOCKS_PER_SEC);
t0 = clock();
for (k=0; k<1000000; k++) {
int a[1000] = {0};
a[420] = 420;
}
printf(" With init: %f secs\n", (double)(clock() - t0) / CLOCKS_PER_SEC);
return 0;
}
#包括
#包括
内部主(空){
时钟t0;
int k;
t0=时钟();
对于(k=0;k我假设堆栈初始化,因为静态数组是自动初始化的。
G++输出
char whatever[2567] = {'\0'};
8048530: 8d 95 f5 f5 ff ff lea -0xa0b(%ebp),%edx
8048536: b8 07 0a 00 00 mov $0xa07,%eax
804853b: 89 44 24 08 mov %eax,0x8(%esp)
804853f: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
8048546: 00
8048547: 89 14 24 mov %edx,(%esp)
804854a: e8 b9 fe ff ff call 8048408 <memset@plt>
char whatever[2567]={'\0'};
8048530:8d 95 f5 ff ff lea-0xa0b(%ebp),%edx
8048536:b8 07 0a 00 mov$0xa07,%eax
804853b:89 44 24 08 mov%eax,0x8(%esp)
804853f:c7 44 24 04 00动产$0x0,0x4(%esp)
8048546: 00
8048547:89 14 24 mov%edx,(%esp)
804854a:e8 b9 fe ff ff呼叫8048408
因此,您使用{'\0'}进行初始化,并完成对memset的调用,因此是的,您的性能受到了影响。如果变量是全局变量或静态变量,则其数据通常会逐字存储在编译后的可执行文件中。因此,char arrBuffer[1024]
将可执行文件大小增加1024字节。初始化可执行文件将确保可执行文件包含您的数据,而不是默认的0或编译器选择的任何数据。程序启动时,无需进行任何处理即可初始化变量
另一方面,堆栈上的变量(如非静态局部函数变量)并非以相同的方式存储在可执行文件中。相反,在函数输入时,空间分配在堆栈上,memcpy将数据放入变量中,从而影响性能。回答您的问题:它可能会影响性能。编译器可能检测到数组的值未被使用,而只是不这样做。这是可能的
我个人认为这是一个个人风格的问题。我很想说:让它保持未初始化状态,并使用一个类似Lint的工具来告诉您是否未初始化地使用它,这肯定是一个bug(与使用默认值而不被告知相反,这也是一个bug,但是一个无声的bug)< p>我认为在声明时要求所有变量默认初始化是一个坏建议。在大多数情况下,这是不必要的,并且会带来性能损失。
例如,我经常使用下面的代码将数字转换为字符串:
char s[24];
sprintf(s, "%d", int_val);
我不会写:
char s[24] = "\0";
sprintf(s, "%d", int_val);
现代编译器能够在未初始化的情况下判断是否使用了变量。您的变量应初始化为有意义的值。盲目而天真地将所有值设置为零并不比不初始化好多少。这可能会使无效代码崩溃,而不是表现出不可预测的行为,但不会使代码出错ect
如果在创建数组时只是为了避免未初始化的变量而天真地将其置零,那么它在逻辑上仍然未初始化。它还没有在应用程序中有意义的值
如果要初始化变量(而且应该),请为它们指定在应用程序中有意义的值。代码的其余部分是否希望数组最初为零?如果是,请将其设置为零。否则,请将其设置为其他有意义的值
或者如果您的代码中的其他代码希望在不先读取它的情况下写入数组,那么无论如何都不要将它初始化。
< P>我个人反对在创建时初始化数组。请考虑下面两段代码。
char buffer[1024] = {0};
for (int i = 0; i < 1000000; ++i)
{
// Use buffer
}
char缓冲区[1024]={0};
对于(int i=0;i<1000000;++i)
{
//使用缓冲区
}
vs
for(int i=0;i<1000000;++i)
{
字符缓冲区[1024]={0};
//使用缓冲区
}
在第一个示例中,为什么要费心初始化缓冲区,因为循环缓冲区周围的第二次不再是0初始化的?除了第一次迭代,我对缓冲区的使用必须在没有初始化的情况下工作。初始化所做的只是消耗时间,使代码膨胀,并掩盖错误(如果我通常只执行一次循环)
作为第二个示例,我当然可以重新考虑代码,但如果我可以重新编写代码,那么我真的想在循环中零初始化缓冲区吗
我怀疑现在大多数编译器都有用非0值填充未初始化变量的选项。我们以这种方式运行所有调试构建,以帮助检测未初始化变量的使用情况,在发布模式下,我们关闭该选项,使变量真正未初始化。正如Sherwood Hu所说,一些编译器可以插入代码来帮助检测未初始化变量的使用情况初始化变量
编辑:
在上面的代码中,我将缓冲区初始化为值0(而不是th)
char s[24] = "\0";
sprintf(s, "%d", int_val);
char buffer[1024] = {0};
for (int i = 0; i < 1000000; ++i)
{
// Use buffer
}
for (int i = 0; i < 1000000; ++i)
{
char buffer[1024] = {0};
// Use buffer
}
char buffer[1024] = {0};
for (int i = 0; i < 1000000; ++i)
{
// Buffer is 0 initialized, so it is fine to call strlen
int len = strlen (buffer);
memset (buffer, 'a', 1024);
}