将变量延迟报告是否更有效?

时间:2011-10-17 20:44:14

标签: c++ performance variables

迟到声明变量会有更多内存或计算效率吗?

示例:

int x;
code
..
.
.
. x is able to be used in all this code
.
actually used here
.
end

code
..
.
.
.
int x;
actually used here
.
end

感谢。

4 个答案:

答案 0 :(得分:9)

写出逻辑上最有意义的东西(通常更接近使用)。编译器可以并且将会发现这样的事情并生成对目标体系结构最有意义的代码。

您的时间比尝试再次猜测编译器与处理器上的缓存的交互更有价值。


例如在x86上这个程序:

#include <iostream>

int main() {
  for (int j = 0; j < 1000; ++j) {
    std::cout << j << std::endl;
  }
  int i = 999;
  std::cout << i << std::endl;
}

与之相比:

#include <iostream>

int main() {
  int i = 999;
  for (int j = 0; j < 1000; ++j) {
    std::cout << j << std::endl;
  }
  std::cout << i << std::endl;
}

编译:

g++ -Wall -Wextra -O4 -S measure.c
g++ -Wall -Wextra -O4 -S measure2.c

使用diff measure*.s检查输出时:

<       .file   "measure2.cc"
---
>       .file   "measure.cc"

即使是:

#include <iostream>

namespace {
  struct foo {
    foo() { }
    ~foo() { }
  };
}

std::ostream& operator<<(std::ostream& out, const foo&) {
  return out << "foo";
}

int main() {
  for (int j = 0; j < 1000; ++j) {
    std::cout << j << std::endl;
  }
  foo i;
  std::cout << i << std::endl;
}

VS

#include <iostream>

namespace {
  struct foo {
    foo() { }
    ~foo() { }
  };
}

std::ostream& operator<<(std::ostream& out, const foo&) {
  return out << "foo";
}

int main() {
  foo i;
  for (int j = 0; j < 1000; ++j) {
    std::cout << j << std::endl;
  }
  std::cout << i << std::endl;
}
除了文件名之外,g++ -S生成的程序集差异的结果仍然相同,因为没有副作用。如果有副作用那么这将决定你构建对象的位置 - 你想在什么时候发生副作用?

答案 1 :(得分:5)

对于int这样的基本类型,从性能的角度来看并不重要。对于class类型,变量定义也包括构造函数调用,如果控制流跳过该变量,则可以省略该调用。此外,对于基本类型和class类型,如果有足够的信息使这种变量有意义,那么定义应该至少延迟到这一点。对于非默认的可构造类类型,这是强制性的;对于其他类型,它可能不是,但它会强制您使用未初始化的状态(如-1或其他无效值)。您应该在尽可能小的范围内尽可能晚地定义变量;从性能的角度来看,它可能并不重要,但它在设计方面总是很重要。

答案 2 :(得分:5)

通常,您应该声明使用变量的位置和时间。它提高了可恢复性,可维护性,并且出于纯粹的实际原因,还提高了记忆位置。

即使你有一个大的物体,你在一个循环体的外部或内部声明它,唯一的区别是在构造和赋值之间;实际的内存分配几乎是相同的,因为当代分配器非常擅长短期分配。

如果你有一小部分代码后来不需要变量,你甚至可以考虑创建新的匿名范围(虽然这通常表明你最好使用单独的函数)。

所以基本上,写出它最具逻辑意义的方式,你通常也会得到最有效的代码;或者至少你不会比通过在顶部宣布所有内容更糟糕。

答案 3 :(得分:4)

对于简单类型,它既不是内存也不是计算上更有效。对于更复杂的类型,使高速缓存中的内容(从构造)接近热点可能更有效。它还可以最大限度地减少内存分配的时间。