编译器会优化和重用变量吗

Posted

技术标签:

【中文标题】编译器会优化和重用变量吗【英文标题】:Will compiler optimize and reuse variable 【发布时间】:2016-10-06 20:15:35 【问题描述】:

例如,如果我有以下代码:

int main()
  myClass a(...);
  a.doSomething();
  if(...)
    myClass c(...);
    c.doSomething();
  

像 gcc 或 clang 这样的普通编译器是否会通过找出“a”在其生命周期内不再使用来优化这些变量的使用,而不是为“c”重新分配空间,而只使用 a 的空间?如果这不适用于类,那么它是否适用于像 double 或 size_t 这样的“传统”类型?

我试图最小化频繁调用函数的分配成本。但是在函数内部的某个地方,我觉得一些旧变量已经没用了,但是不应该将新变量称为那个名称。编译器会直接为我重用变量还是我应该做类似的事情

myClass a(...);
something(a);
if(...)
  #define c a
  c=myClass(...);
  something c;
  #undef c

【问题讨论】:

您的分析器是否告诉您这是应用程序中的热点,生成的程序集说明了什么? 怎么样: myClass a; a.doSomething(); if (...) myClass c; c.doSomething(); GCC 并没有很好地重用堆栈空间,即使函数体中的作用域很短。但我相信它已经做得更好了。 堆栈分配的 C++ 类实例的答案可能与 C 标量不同。而且由于您显然专注于类实例,因此应该从标记列表中删除 [c]。 @GManNickG 这是一个在 main 中调用了大约 1,000,000 次的函数,存储成本很高,我不能在 main 中内联它,因为我需要它是递归的。尚未尝试分析器或生成程序集。 【参考方案1】:

一般情况下,编译器不允许重用a,直到其作用域结束,即函数末尾的右大括号。当析构函数执行一些特殊代码时,此功能(在可预测的时间销毁对象)可以在 C++ 中创建守卫*

我试图最小化频繁调用函数的分配成本。

由于分配自动变量几乎没有任何成本,大部分成本是调用构造函数。这不是您可以优化的东西。

* 如果你的对象有普通的析构函数,编译器可以重用内存。这会节省你的记忆,而不是时间。

【讨论】:

每个对象都有一个析构函数。【参考方案2】:

这些变量分配在堆栈上。即使编译器不重用空间,这也不会导致任何额外的 CPU 指令,只有 RAM。堆栈上的分配只是将分配的字节数添加到堆栈指针。通常它是通过添加函数中存在的所有变量的大小来使用一条指令完成的。在任何情况下,编译器都足够聪明,可以重用分配变量的 CPU 寄存器。

注意,如果你的类有析构函数,那么它们必须持续到块的末尾。因此在这种情况下,变量a 的内存将不会被重用,因为它在函数结束时需要。但是编译器仍然可以重用用于它的寄存器。

【讨论】:

它必须在堆栈上吗?这些只是“自动”变量。使用堆栈取决于实现。 好吧,它们可能会被优化出来并放在寄存器中。在这种情况下,分配和寄存器重用是没有成本的,编译器必须做得足够好。

以上是关于编译器会优化和重用变量吗的主要内容,如果未能解决你的问题,请参考以下文章

编译器内存优化 - 重用现有块

GCC优化技巧,真的有用吗?

这是常见的优化吗?

编译器可以通过指向易失性的指针优化存储吗? [复制]

C# 编译器会优化这段代码吗?

GCC 可以使用编译时常量变量优化类的方法吗?