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

时间:2011-10-10 20:23:53

标签: c++ visual-c++

char buffer[1000] = {0};

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

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

  1. 该数组具有固定大小且在编译时已知
  2. 数组位于堆栈上,这意味着可执行文件可能包含可执行文件数据段(在Windows上)中的数据,作为已填充0的数据块。
  3. 请注意,答案对于任何编译器都是通用的,但我特别感兴趣的是在Windows上的MSVC编译器(任何版本)上测试的答案。

    奖励积分:非常感谢有关此细节的任何文章,白皮书等的链接。

6 个答案:

答案 0 :(得分:8)

如果它在一个函数内部,不,它不是恒定的时间。

你的第二个假设是不正确的:

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

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

因此无法在O(1)中执行此操作,因为它必须将其归零。

答案 1 :(得分:6)

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

Stack是一个共享内存,你需要主动为零,总是希望在那里有1000个零。您定义的数组不是作为指向数据段的指针实现的,它是堆栈上的1000个变量,必须在O(1000)中初始化。

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

答案 2 :(得分:4)

它永远不会是恒定时间,全球与否。编译器初始化它是真的,但操作系统必须将所有文件加载到内存中,这需要O(n)时间。

答案 3 :(得分:1)

  

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

如果你进入定义数组的函数怎么办?全局DATA段需要为每个函数调用提供此数组的副本,以允许每个函数都有自己的数组来处理。编译器必须运行您的代码以确定将发生的最大递归。

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

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

答案 4 :(得分:0)

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

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

这里,堆栈指针'esp'减10,为某些局部函数变量腾出空间。它们不是初始化......需要循环。

This文章似乎很友好。

答案 5 :(得分:-1)

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