【问题标题】:Init count loop variable out or inside the loop declaration in C/C++在 C/C++ 中的循环声明外或内初始化计数循环变量
【发布时间】:2021-04-14 16:55:40
【问题描述】:

也许是一个愚蠢的问题,但我想知道循环内部或外部的循环计数器(int i = 0 或 size_t i = 0)的声明是否会影响循环的性能。例如:

// Declaration of counter out of the loop:
int i = 0;
for(i = 0; i < iters; i++) {
    // do something
}

// Declaration of counter inside of the loop:
for(int i = 0; i < iters; i++) {
    // do something
}

我知道编译器在这两种情况下只在内部创建一次计数器变量,因此,没有任何区别......对吗?

【问题讨论】:

  • 您的编译器有一个选项可以生成已编译代码的汇编列表。您是否尝试过编译这两个版本,然后查看编译器生成的代码是否相同或不同?
  • 不,我没有检查两个版本中生成的汇编代码......好点。我将自己检查并发布痕迹。我正在使用类似于 C99 的 OpenCL,所以我想这将类似于 C 和 OpenCL 的痕迹
  • 非常方便的工具,可以快速查看不同编译器和编译器选项如何转换代码:godbolt.org
  • 也不要误以为更短的代码就是更快的代码。通常它是,但看起来非常简单,短代码可以做 CPU 讨厌做的事情,比如用糟糕的内存访问模式滥用缓存,并且最终花费的时间比长时间执行相同工作的程序要长得多大大地。只有在证明简单太慢之后,才能追求简单并担心快速。
  • 一个非常重要的考虑因素是变量的“范围”。目标是最小化“范围” 一种方法是:for(int i = 0; i &lt; iters; i++) { 另一种方式,如您的示例代码所示,导致变量的“范围”是变量声明之后的所有文件。

标签: c++ c performance loops


【解决方案1】:

启用优化的优秀现代编译器会根据标识符的使用位置生成代码,而不管它在何处声明(受 C 标准或其他规则要求的语义)。这应该包括冗余初始化;编译器应该认识到涉及i的实际效果是它需要在循环开始之前被初始化(并且不需要更早地初始化),它在循环中使用,并且它在循环之后不使用循环(除非它用于问题中未显示的代码)。

因此在这种情况下不会有性能差异。

代码对人类的影响和互动方式有所不同。标识符从使用它的位置声明得越远,在两者之间的代码中出现错误的机会就越大。为了减少错误,请在您需要的地方声明一个标识符,并设法将其范围限制在需要它的代码范围内。

此外,声明和使用之间的距离越远,人们就越难以理解源代码,因为它变得越来越复杂。因此,为了帮助人们将来理解、修改和调试您的源代码,请限制标识符的范围。

(对此有一些例外。例如,这条规则会让你在使用它们的函数内部声明外部函数。但函数声明通常放在任何其他函数之外。这样做有一些好处:如果一个函数在任何函数之外声明并且也在同一个源文件中定义,那么声明在定义发生的地方是可见的,如果他们不同意,编译器将提供警告或错误消息,从而捕获错误。如果函数是没有在同一个文件中定义,那么通常它的声明应该由头文件提供,并且头文件通常应该包含在任何函数之外,带有#include指令,部分原因是它们可能包含其他不合适的声明在里面一个函数。)

【讨论】:

    猜你喜欢
    • 2017-07-20
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 2016-02-23
    • 2012-02-06
    相关资源
    最近更新 更多