繁体   English   中英

在恒定时间内初始化C ++数组

[英]Initializing C++ array in constant time

char buffer[1000] = {0};

这会将所有1000个元素初始化为0。这是恒定时间吗? 如果没有,为什么?

似乎编译器可以根据以下事实将此优化为O(1):

  1. 数组大小固定,在编译时已知
  2. 该数组位于堆栈上,这意味着可执行文件可能将此数据包含在可执行文件的数据段中(在Windows上),作为一块已经充满0的数据。

请注意,答案可以是任何编译器通用的,但是我对Windows上的MSVC编译器(任何版本)上测试的答案特别感兴趣。

奖励积分:链接到任何有关此详细信息的文章,白皮书等,将不胜感激。

如果在函数内部,则不是固定时间。

您的第二个假设不正确:

“该数组位于堆栈上,这意味着该可执行文件可能在可执行文件的数据段中(在Windows上)包含已填充0的数据块。

堆栈尚未填充零。 它充满了以前的函数调用中剩下的垃圾。

因此不可能在O(1)执行此操作,因为它必须将其清零。

它只能是O(1)作为全局变量。 如果它是局部变量(在堆栈上),则为O(n),其中n是数组的大小。

堆栈是一个共享内存,您始终需要主动置零,而您要一直在其中拥有1000个零。 像您定义的数组未实现为指向数据段的指针,它是堆栈上的1000个变量,必须在O(1000)中初始化。

编辑:Dani是正确的,我必须修正我的声明:如果它是一个全局数组,则它将在程序启动时初始化。 它也是O(n)。

无论是不是全局时间,永远都不会是恒定时间。 确实,编译器会对此进行初始化,但是操作系统必须将所有文件加载到内存中,这需要O(n)时间。

该数组位于堆栈上,这意味着可执行文件可能将此数据包含在可执行文件的数据段中(在Windows上),作为一块已经充满0的数据。

如果您递归到定义数组的函数该怎么办? 对于每个函数调用,全局DATA段都需要具有该数组的副本,以允许每个函数具有自己的数组进行工作。 编译器将必须运行您的代码来确定将要进行的最大递归。

当程序中有多个线程并且每个线程都调用foo时,还会发生什么情况? 突然之间,您在DATA中共享了必须锁定的内容。 锁定可能会导致比摆脱初始化更多的性能问题。

我也不会太担心。 大多数平台都有相当有效的零填充内存方式。 除非您概要分析并发现问题,否则不要流汗。

正如其他人指出的那样,假设2是错误的。 堆栈变量在运行时以O(1)的时间分配,但是除非您正在运行调试版本,否则通常不会初始化堆栈变量。

PUSH ebp
MOV  ebp, esp
SUB  esp, 10
// function body code goes here

此处,堆栈指针“ esp”递减10,以为某些局部函数变量腾出空间。 它们没有被初始化……这需要循环。

这篇文章似乎足够友好。

如果是全局静态变量,则此处的“常量”为零-初始化是在COMPILE TIME进行的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM