延迟声明变量是否更有效?
Is it more efficient to declare variables late?
延迟声明变量是否会增加内存或可能提高计算效率?
的例子:
int x;
code
..
.
.
. x is able to be used in all this code
.
actually used here
.
end
和
code
..
.
.
.
int x;
actually used here
.
end
谢谢。
写逻辑上最有意义的东西(通常更接近使用)。编译器能够并且将会发现这样的事情,并生成最适合您的目标体系结构的代码。
您的时间远比尝试猜测编译器和处理器上的缓存的交互更有价值。
例如在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;
}
和
#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
生成的程序集的diff的结果除了文件名之外仍然是相同的,因为没有副作用。如果有副作用,那么这将决定你在哪里构建对象——你希望副作用在什么时候发生?
对于基本类型,如int
,从性能的角度来看,这无关紧要。对于class
类型,变量定义还包括构造函数调用,如果控制流跳过该变量,则可以提交构造函数调用。此外,对于基本类型和class
类型,定义至少应该延迟到有足够的信息使这种变量有意义的时候。对于非默认的可构造类类型,这是强制性的;对于其他类型,它可能不是,但它迫使您使用未初始化的状态(如-1或其他无效值)。你应该尽可能晚地定义变量,在尽可能小的范围内;从性能的角度来看,这可能并不重要,但从设计的角度来看,这总是很重要的。
一般来说,应该声明在何时何地使用这些变量。它提高了可靠性、可维护性,并且出于纯粹实用的原因,提高了内存局域性。
即使你有一个大对象,并且你在循环体外部或内部声明它,唯一的区别是构造和赋值;实际的内存分配实际上是相同的,因为当代的分配器非常擅长短期分配。
你甚至可以考虑创建新的,匿名作用域,如果你有一小部分代码的变量是不需要的(尽管这通常表明你最好使用一个单独的函数)。
所以基本上,以最合乎逻辑的方式编写,你通常也会得到最有效的代码;或者至少你不会比在顶部声明所有内容更糟糕。
对于简单类型,这两种方法既不提高内存效率,也不提高计算效率。对于更复杂的类型,在使用它们的地方附近将内容放在缓存中(从构造开始)可能会更有效。它还可以最小化内存剩余分配的时间。
- 如果变量名称不跟在 char* 后面,const char* 是否有效?
- 钳制迭代器是否有效
- 检查由括号、方括号和大括号组成的一组方括号是否有效?
- 在函数内创建的对象的范围 - 如果在函数外部存储和访问引用,它们是否有效?
- 模板签名解析为 void(void) 被 GCC 拒绝;这是否有效C++?
- 我如何知道作为参数的size_t在函数中是否有效?
- 是否可以在C++中获取 CHAR 的有效十六进制地址?
- 我的运算符重载是否有效<<(流插入)左操作数不是 ostream
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 模板变量是否允许在多个翻译单元中并有效合并?
- 错误:在尝试检测 std::cout 是否<< t 时,功能强制转换为数组类型;有效
- 声明后,gcc 的动态大小数组是否与标准数组有效相同?
- 此递归模板类型定义是否有效C++?
- 将 C 函数转换为 C++ 以检查数字是否有效
- 函数参数的名称与调用函数时使用的变量相同是否有效?
- 如何检查输入是否有效?
- 如何检查用户的输入是否有效以及我正在寻找的数字?
- 堆分配对于大型块中的分页是否更有效?
- 在函数中按值传递 unordered_map/unordered_set 是否有效? C++
- 如何检查isupper(cstr)是否有效?