代码之家  ›  专栏  ›  技术社区  ›  Michael Dickens

C变量声明的效率[副本]

  •  7
  • Michael Dickens  · 技术社区  · 16 年前

    例如,用C语言声明变量需要多长时间 int x unsigned long long var ?我想知道在这种情况下,它是否会使我的代码更快。

    for (conditions) {
        int var = 0;
        // code
    }
    

    这样做会更快还是更容易?

    int var;
    for (conditions) {
        var = 0;
        // code
    }
    

    谢谢你的帮助。

    12 回复  |  直到 14 年前
        1
  •  8
  •   Robert Cartaino    16 年前

    每当您对性能有疑问时,最好的方法就是围绕它(数百万次迭代)循环并计时。但在这种情况下,你很可能会发现 这没什么区别。

    更重要的是要正确地表达代码的意图。 如果需要循环外的变量,请将其延迟到循环外。如果你 只有 需要循环内的变量,请在循环内声明它。

    您应该始终在尽可能窄的范围内声明和初始化变量。

    无论如何,您不应该担心这些类型的微优化(除了 最稀有的 病例)。如果你 真正地 需要担心潜在的纳米二次性能改进,测量差异。变量声明不太可能成为应用程序中最大的瓶颈。

        2
  •  14
  •   Ned Batchelder    16 年前

    一条建议是:不要担心哪种语言的结构在微观上比其他语言快或慢,而应该关注哪种语言能让你最好地表达自己。

    此外,要找出代码的花费时间,请使用探查器。

    正如其他人指出的,声明纯粹是编译时的事情,它们不会影响执行时间。

        3
  •  9
  •   AnT stands with Russia    16 年前

    这没什么区别。在传统的实现中,声明本身(不包括初始化)不生成机器指令。函数序言代码通常一次为所有局部变量分配堆栈中的空间,而不管它们在哪里声明。

    但是,至少在理论上,如果声明局部变量,则会间接影响代码的性能。当您尽可能在本地声明变量(第一个变量)时,通常情况下,它会导致函数为其局部变量保留的堆栈帧较小(因为堆栈中的相同位置可以在不同的时间由不同的局部变量共享)。具有较小的堆栈帧可以减少一般的堆栈内存消耗,即,当执行嵌套函数调用时,堆栈大小不会增长得那么快(在递归函数中尤其明显)。由于新的堆栈页分配发生的频率较低,并且堆栈内存位置变得更好,所以通常可以提高性能。

    当然,后一个考虑因素取决于平台。它可能对您的平台和/或应用程序影响很小或没有影响。

        4
  •  5
  •   rlbond    16 年前

    根本不需要时间。全局变量的内存在启动时分配,“声明”堆栈上的变量只涉及调用函数时堆栈指针向上移动的距离。

        5
  •  4
  •   PerfTLL John Knoeller    14 年前

    声明纯粹是编译时的,它们在运行时不需要任何开销。但是第一段代码还是比第二段好,原因有两个

    • 当您声明变量时,应该总是初始化它们,这样它们就永远不会有未初始化的值。这与
    • 始终对变量声明使用尽可能窄的范围

    所以你的第一个例子,虽然不比第二个快,但仍然更好。

    所有那些插嘴告诉他不要过早或微观优化他的代码的人都是错误的。它永远不会 坏的 了解各种代码的开销。最优秀的程序员有一个坚实的,几乎不连贯的,掌握各种策略的成本,并在设计时自动考虑到这一点。当你是一个初学者的时候,你成为程序员的方式就是问这种问题。

    实际上,当每个函数为局部变量分配空间时,成本很小,但是无论有多少个局部变量,成本都是相同的*。

    *好吧,这不是真的,但是成本只取决于空间总量,而不是变量的数量。

        6
  •  3
  •   Drew Dormann    16 年前

    声明一点也不花时间。

    编译器会将该行解释为一个通知,通知它的空间需要存在于堆栈上。

        7
  •  1
  •   EMP    16 年前

    正如其他人已经说过的,这不应该花费任何时间。因此,您需要基于其他因素做出这个决定:什么会使您的代码更可读,更不容易出现错误。通常认为,最好尽可能接近变量的用法来声明变量(这样您就可以一次看到声明和用法)。如果它只在内部作用域中使用,那么只需在该作用域中声明它——忽略这个作用域的性能。

        8
  •  1
  •   Larry Watanabe    16 年前

    声明变量确实需要时间,因为它会导致机器语言指令为堆栈上的变量分配空间。这只是堆栈指针的一个增量,需要很小但非零的时间。

    我相信您的问题是,如果变量在循环中声明,是否需要更多的时间(即更多的堆栈增量操作)。答案是否定的,因为堆栈只对循环块递增一次,而不是每次执行循环时。因此,无论哪种方式,时间都没有区别,即使循环执行无数次。

        9
  •  1
  •   benzado    16 年前

    免责声明:具体发生的事情取决于您的编译器、体系结构等,但概念上是这样的:

    当您在一个方法中声明一个变量时,它将在堆栈上分配。在堆栈上分配某些内容只涉及到按变量大小向上移动堆栈指针。例如,如果 SP 表示堆栈顶部的内存地址,声明 char x 结果在 SP += 1 int x 结果在 SP += 4 (在32位机器上)。

    当函数退出时,堆栈指针将返回到调用方法之前的位置。因此,处理所有事务也很快。

    所以,不管是哪种方式,它都只是一个加法,不管数据量多少,它都需要相同的时间。

    一个智能编译器将把几个变量声明组合成一个加法。

    当您在循环中声明一个变量时,理论上它可以通过循环在每次迭代中更改堆栈指针,但同样,智能编译器可能不会这样做。

    (一个值得注意的例外是C++,它需要额外的工作,因为当创建或销毁了堆栈分配的对象时,它需要调用构造函数和析构函数)。

        10
  •  1
  •   Federico A. Ramponi    16 年前

    我一纳秒都不在乎。除非你需要访问它的价值 之后 for循环结束后,将变量留在循环中:它将更接近使用它的代码(您的代码将更可读),并且其范围将由循环本身限定(您的代码将更优雅,不易出错)。

        11
  •  1
  •   Nicolás    16 年前

    我打赌编译后的二进制文件在这两种情况下都是相同的。

        12
  •  0
  •   Inso Reiges    16 年前

    编译器将变量声明转换为堆栈空间保留。现在,如何工作完全依赖于平台。在x86和几乎所有流行的体系结构上,这只是堆栈帧地址的减法和/或从堆栈顶部访问的索引寻址模式。所有这些都需要一个简单的减法/加法,即 真正地 无关紧要。

    技术上讲 第二个示例效率较低,因为声明发生在循环范围的每个条目上,即每个循环迭代上。但是,堆栈空间只保留一次的可能性是99.99%,即使是赋值操作也会被优化掉,尽管技术上应该在每个循环迭代中完成。现在在C++中,情况会变得更糟, 如果 变量有一个构造函数,然后将在每个循环迭代中运行。

    作为底线,如果没有适当的分析,您真的不应该担心任何此类问题。即使这样,在这里也有很多更有价值的问题要问你自己,比如“什么是最易读的方法,什么更容易理解和维护等等”。

    推荐文章