Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 晚声明变量是否更有效?_C++_Performance_Variables - Fatal编程技术网

C++ 晚声明变量是否更有效?

C++ 晚声明变量是否更有效?,c++,performance,variables,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 谢谢。对于简单类型来说,无论是内存还是计算效率都不高。对于更复杂的类型,将内容放在缓存中(从正在构建的缓存中)使用位置附近可能更有效。它还可以最大限度地减少内存保持分配的时间。对于

延迟声明变量是内存更大还是计算效率更高

例如:

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

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

谢谢。

对于简单类型来说,无论是内存还是计算效率都不高。对于更复杂的类型,将内容放在缓存中(从正在构建的缓存中)使用位置附近可能更有效。它还可以最大限度地减少内存保持分配的时间。

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

写逻辑上最有意义的东西(通常更接近使用)。编译器可以并且将发现类似的情况,并生成最适合您的目标体系结构的代码

您的时间远比试图猜测编译器和处理器上缓存的交互更有价值


例如,在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;
}
使用
diff measure*.s
检查输出时,给出:

<       .file   "measure2.cc"
---
>       .file   "measure.cc"
<.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;
}
#包括
名称空间{
结构foo{
foo(){}
~foo(){}
};
}

std::ostream&operator通常,您应该声明使用变量的位置和时间。它提高了可靠性、可维护性,并且出于纯粹的实际原因,提高了内存局部性

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

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


因此,基本上,以最符合逻辑的方式编写代码,通常也会得到最高效的代码;或者,至少你不会比在顶部声明所有内容更糟。

可能最好将
x
保留在使用它的地方,因为程序员会保持一个更清晰的头脑和对代码的看法,专注于算法,而不是这些细节;它起源于帕斯卡和相关语言的古老时代,并且刚刚流传下来。它实际上是C89的遗物,当时编译器需要预先查看所有变量以确定堆栈大小。现代编译器在初始化变量之前是不会分配堆栈空间的,即使它是在更早的时候声明的。另一方面,如果构造需要一个昂贵的操作,比如从主存读取,那么在非依赖操作同时完成的情况下,更早地将其流水线化可能会更有效。True。如果施工有副作用,你可能无法选择在何处施工。最接近一般规则的是,通常最好把它们放在使用它们的地方,但如果你有任何理由不这样做,这通常就足够了。+1对于
来说,你的时间远比猜测编译器和处理器上缓存的交互作用更有价值。
我希望更多的人能让这项技术继续优化99%的代码,并继续做一些更有效率的事情@AAT——可能还有第三件事要避免事后猜测——未来十年处理器的行为!
<       .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;
}
#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;
}