全局或局部变量是否更有效?

时间:2016-08-19 18:46:55

标签: c++

在游戏中,计算渲染最后一帧(增量时间)以产生平滑移动,定时器等所花费的时间非常常见。

这样做的一种方法是声明3个全局变量:

float deltaTime, currentTime, elapsedTime;

然后计算游戏循环开始时的增量时间:

currentTime = getTime();
deltaTime = currentTime - elapsedTime;
elapsedTime = currentTime;

(其中getTime()是一个返回自程序启动以来的时间的函数)

另一种方法是将 deltaTime currentTime 声明为局部变量:

float currentTime = glfwGetTime();
float deltaTime = currentTime - elapsedTime;
elapsedTime = currentTime;

如果我的理解是正确的,那么编译器必须在循环结束时释放变量的内存,并且在循环的下一次迭代中,再次重新分配它,导致它比仅仅声明更低效全局变量。

这是正确的还是在后台自动发生的其他一些我不知道的事情?

2 个答案:

答案 0 :(得分:7)

  

如果我的理解是正确的,那么编译器必须在循环结束时释放变量的内存,并且在循环的下一次迭代中,再次重新分配它,导致它比仅仅声明更低效全局变量。

那不是真的。

编译器不在循环中为局部变量分配和释放内存。通常,在创建函数的堆栈帧时分配函数中局部变量的内存。

变量在循环的每次运行中初始化。

如果变量是一个具有构造函数和析构函数的类类型,它们将在循环的每次运行中被调用,这可能是昂贵的,这取决于构造函数和析构函数中发生的事情,循环的次数是运行

对于float类型,由于在循环中使用局部变量,不应该有任何开销。如果有的话,我会非常惊讶。

答案 1 :(得分:1)

源代码:

extern float getTime();
float deltaTime, currentTime = getTime(), elapsedTime = getTime();

float time_it()
{
  currentTime = getTime();
  deltaTime = currentTime - elapsedTime;
  elapsedTime = currentTime;
  return deltaTime;
}

目标代码:

time_it():
        sub     rsp, 8
        call    getTime()
        vmovss  DWORD PTR currentTime[rip], xmm0
        vmovaps xmm1, xmm0
        vsubss  xmm0, xmm0, DWORD PTR elapsedTime[rip]
        vmovss  DWORD PTR elapsedTime[rip], xmm1
        vmovss  DWORD PTR deltaTime[rip], xmm0
        add     rsp, 8
        ret

什么是重要的?

call getTime() - 迄今为止在任何系统上最昂贵的操作

vmovss DWORD PTR currentTime[rip], xmm0一次内存写

一次内存提取: vsubss xmm0, xmm0, DWORD PTR elapsedTime[rip]

两次内存写入,其中一次是冗余的。

vmovss DWORD PTR elapsedTime[rip], xmm1 vmovss DWORD PTR deltaTime[rip], xmm0

在全局中存储deltaTime的总开销是一次内存写入。没有什么比表现更好的,但肯定是不受欢迎的风格。

避免全局变量的原因与性能无关,它与避免紧耦合有关。