【问题标题】:Does it matter when variables are initialised? [duplicate]初始化变量时是否重要? [复制]
【发布时间】:2016-03-13 03:05:48
【问题描述】:

关于空间和时间利用的数量和效率,以下在 C++ 中是否存在差异,答案是否取决于编译器?

int main() {
    int a, b = 0;
    doSomething1(b);
    a = 9;
    doSomething2(a);
    return 0;
}
int main() {
    int a = 0, b = 0;
    doSomething1(b);
    a = 9;
    doSomething2(a);
    return 0;
}
int main() {
    int b = 0;
    doSomething1(b);
    int a = 9;
    doSomething2(a);
    return 0;
}

编辑:此问题已被标记为与this 重复,我认为这是不正确的,因为

  1. 另一个问题是询问变量——无论它们在函数中的什么位置——是否应该在一开始就声明,或者它们是否应该只在使用它的代码块中声明(即最局部的范围)。
  2. 我的问题是问是否存在性能差异,在空间或时间方面,在函数的最开始初始化变量,或仅在需要它的点在同一范围内

请查看此问题的标记。它不是重复的。

【问题讨论】:

  • 如果您阅读了重复问题中的答案(在我看来),它似乎可以回答您的问题。重复横幅的重点并不是说这两个问题完全相同,而是重复问题的答案也可以作为该问题的答案。
  • 您是否尝试过查看生成的代码(通过您的优化编译器)?

标签: c++ initialization


【解决方案1】:

原则上,任何符合 C++11 的实现都应该表现出等效行为(而“等效”的含义很难理解,棘手的概念是:undefined behavior)。

在实践中,我认为最好在其声明处(或附近)初始化每个变量(如您的第二个示例)。代码可能更容易阅读,并且会表现出更多的确定性行为。

使用最近的GCC,当使用g++ -std=c++11 -Wall -Wextra -g 编译时,您将收到有关未初始化变量的有用警告。

关于性能,当询问optimize(例如g++ -std=c++11 -O2)时,编译器将删除无用的初始化 - 特别是对于局部变量 - (因此始终初始化变量实际上不会影响生成代码的性能)。

我的问题是询问在函数开始时初始化变量是否存在空间或时间方面的性能差异,或者仅在同一范围内需要它的点

可能在性能上没有实际差异,但是 C++11 标准不太关心性能(并且更关心遵守)。性能是实施质量问题。

如果您非常关心性能,则需要基准测试。但不要忘记在你的编译器中启用optimizations(例如g++ -march=native -O2);我想您不会注意到任何显着的性能差异(因此,如果您可靠地测量某些差异,它可能只是百分比的一小部分)。

请查看生成的汇编代码内部(例如使用g++ -S -fverbose-asm -O2,然后查看*.s 生成的汇编文件)。使用GCC,您还可以通过-fdump-tree-all 获取数百个 转储文件,解释发生了什么优化(但您将花费数天时间研究它们)。

【讨论】:

  • 在性能方面,第一个和第三个 main() 在声明 a 的时间上是否有区别?
  • 我很惊讶 g++ 可以删除无用的初始化:g++ 怎么知道它是无用的(除非它是非导出符号?)。你有更多相关信息吗?
  • 它是特定于实现的,取决于您在编译器中启用的优化。但大多数优化编译器会生成性能相似的代码
  • @thegreatjedi Basile 可能比我更了解这一点,但如果有区别,我会感到非常惊讶。可能出现的两种可能性是:(1)a 未使用的初始化为零将被优化掉。如今,编译器可以很好地捕获没有效果的代码。 (@qdii:它是一个局部变量,在其他任何地方都不可见。) (2) 堆栈的大小可以在函数中间再次调整以适应 a,这与第一个示例相反,堆栈是立即分配的永远。 (这就是你所害怕的吗?)如果真的发生的话,它会非常便宜。
猜你喜欢
  • 1970-01-01
  • 2017-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
相关资源
最近更新 更多