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;
}