我们是否应该将临时变量用于返回的函数值

Should we use temporary variables for the returned values of functions?

本文关键字:返回 用于 函数 变量 是否 我们      更新时间:2023-10-16

我对此进行了考虑:这两个实践中是否存在性能差异:

  1. 将函数的返回值存储在临时变量中将该变量作为另一个函数的参数。
  2. 将功能放入另一个功能。

规格

假设所有类和功能都正确编写。

案例1。

ClassA a = function1();
ClassB b = function2(a);
function3(b);

案例2。

function3(function2(function1()));

我知道只有一次运行没有很大的区别,但是认为我们可以在循环中运行很多次,我创建了一些测试。

测试

#include <iostream>
#include <ctime>
#include <math.h>
using namespace std;
int main()
{
   clock_t start = clock();
   clock_t ends = clock();
   // Case 1.
   start = clock();
   for (int i=0; i<10000000; i++)
   {
      double a = cos(1);
      double b = pow(a, 2);
      sqrt(b);
   }
   ends = clock();
   cout << (double) (ends - start) / CLOCKS_PER_SEC << endl;
   // Case 2.
   start = clock();
   for (int i=0; i<10000000; i++)
      sqrt(pow(cos(1),2));
   ends = clock();
   cout << (double) (ends - start) / CLOCKS_PER_SEC << endl;
   return 0;
}

结果

  • 案例1 = 6.375
  • 案例2 = 0.031

为什么第一个要慢得多,如果第二个更快,为什么我们不总是以这种方式编写代码?无论如何,第二个普拉蒂斯有名字吗?
我还想知道,如果我在第一种情况下创建for循环之外的变量会发生什么,但是结果是相同的。为什么?

如果您想要计算紧缩并且您的数字变得更加一致,请打破抛出的全部优化。确保获得正确值的代码实际上运行而不是完全抛弃,我将两个测试的结果分配给了挥发性的本地(这不是完全适当的挥发性使用,但确实如此仅确保价值创建的一个不错的工作是重要的三角洲)。

#include <iostream>
#include <ctime>
#include <cmath>
using namespace std;
int main()
{
    clock_t start;
    volatile double val;
    for (int j=1;j<=10;j++)
    {
        // Case 1.
        start = clock();
        for (int i=0; i<2000000; i++)
        {
            double a = cos(1);
            double b = pow(a, 2);
            val = sqrt(b);
        }
        cout << j << ':' << (double) (clock() - start) / CLOCKS_PER_SEC << endl;
        // Case 2.
        start = clock();
        for (int i=0; i<2000000; i++)
            val = sqrt(pow(cos(1),2));
        cout << j << ':' << (double) (clock() - start) / CLOCKS_PER_SEC << endl << endl;
    }
    return 0;
}

在我的MacBook Air上产生以下版本编译的输出(无论如何都不是速度恶魔):

1:0.001465
1:0.001305
2:0.001292
2:0.001424
3:0.001297
3:0.001351
4:0.001366
4:0.001342
5:0.001196
5:0.001376
6:0.001341
6:0.001303
7:0.001396
7:0.001422
8:0.001429
8:0.001427
9:0.001408
9:0.001398
10:0.001317
10:0.001353

上面两个循环的适当和法律完全优化是"甚至不做循环"。您可以很容易地看到一种情况,即您在第一种情况下使用非初始化的变量混淆了编译器,或者您对变量的使用混淆了,或者您的优化级别的功能实际上存在。

>>

现在,涉及临时变量隐式移动的C 11中的两者之间存在差异,但是您可以使用std::move解决此问题。(我不确定,但是最后一个超出范围的局部变量的用法可能有资格用于隐式移动)。对于double,这不是区别,但对于更复杂的类型,可以是。