你老师的建议过于简单化了一个复杂的话题。
如果您将“中间”视为一个单个术语(在这个词的算术意义上),那么问问自己,您的代码是否在其他任何地方重复使用该术语? IE。如果你有这样的代码:
void calculate_sphere_parameters(double radius, double & area, double & volume)
{
area = 4 * (4 * acos(1)) * radius * radius;
volume = 4 * (4 * acos(1)) * radius * radius * radius / 3;
}
你是否应该写:
void calculate_sphere_parameters(double radius, double & area, double *volume)
{
double quarter_pi = acos(1);
double pi = 4 * quarter_pi;
double four_pi = 4 * pi;
double four_thirds_pi = four_pi / 3;
double radius_squared = radius * radius;
double radius_cubed = radius_squared * radius;
area = four_pi * radius_squared;
volume = four_thirds_pi * radius_cubed; // maybe use "(area * radius) / 3" ?
}
现代优化编译器不太可能为这两者生成相同的二进制代码。我把它留给读者来决定他们更喜欢在源代码中看到什么......
对于许多简单的算术也是如此(至少,如果计算中不涉及函数调用)。除此之外,现代编译器和/或 CPU 指令集可能能够免费进行“偏移”计算,例如:
for (int i = 0; i < N; i++) {
do_something_with(i, i + 25, i + 314159);
}
结果与以下相同:
for (int i = 0; i < N; i++) {
int j = i + 25;
int k = i + 314159;
do_something_with(i, j, k);
}
因此,主要规则应该是,如果您的代码的可读性不能从创建一个新变量来保存“临时”计算的结果中受益,那么使用一个可能有点矫枉过正。
另一方面,如果您在 10 行代码中使用了十几次 i + 12345... 说出它的名字,并评论为什么这个奇怪的硬编码偏移量如此重要。
请记住,仅仅因为您的源代码 包含变量并不意味着编译器发出的二进制代码将为该变量分配内存。编译器可能会得出结论,该值甚至没有被使用(并完全放弃分配它的计算),或者它可能得出结论它“只是一个中间值”(以后再也不会使用它应该是从内存中检索)并将其存储在寄存器中,以便在“最后一次使用”后覆盖。每次需要时计算值i + 1 比从内存位置检索它要高效得多。
我的建议是:
- 首先要保持代码可读性 - 变量太多而不是帮助而不是晦涩难懂。
- 不必费心保存“简单”中间值 - 加/减或按 2 的幂缩放几乎是“免费”操作
- 如果您在多个地方重复使用相同的值(“算术项”),如果计算成本很高(例如涉及函数调用、长的算术序列或大量内存访问,如数组校验和),请保存它)。