繁体   English   中英

将函数内部的大变量声明为`static`是否有任何性能差异?

[英]Is there any difference in performance to declare a large variable inside a function as `static`?

不确定之前是否已经提出这个问题。 在回答这个非常简单的问题时 ,我问自己以下问题。 考虑一下:

void foo()
{
    int i{};
    const ReallyAnyType[] data = { item1, item2, item3,
        /* many items that may be potentially heavy to recreate, e.g. of class type */ };
    /* function code here... */
}

现在理论上,每次控制到达功能时都会重新创建局部变量,对吧? 即看上面的int i - 它肯定会在堆栈上重新创建。 上面的数组怎么样? 编译器可以像智能一样优化其创建只发生一次,或者我还需要static修改器吗? 如果数组不是const怎么办? (好吧,如果它不是const ,那么在创建它时可能只有一次感觉,因为在函数执行期间进行修改时,可能需要在调用之间重新初始化为默认状态。)

可能听起来像一个基本问题,但出于某种原因,我仍然在思考。 另外,忽略“你为什么要这样做” - 这只是一个语言问题,不适用于某个编程问题或设计。 我的意思是C和C ++。 如果这两个问题存在差异,请概述这些问题。

我想这里有两个问题:

  • 编译器可以优化非static const对象进行有效static使得它不仅创造一次;

  • 给定的编译器是否会这样做是合理的期望。

我认为第二个问题的答案是“否”,因为我没有看到进行大量控制流分析以保存程序员输入单词static的麻烦。 然而,我经常对人们花时间写作的优化感到惊讶(与认为他们应该进行的优化相反:-))。 同样,如果那就是你想要的,我强烈建议使用static这个词。

对于第一个问题,在某些情况下,编译器可以根据“as-if”规则执行优化,但在极少数情况下会解决。

首先,如果初始化程序中的任何对象或子对象具有非平凡的构造函数/析构函数,则构造/销毁是可见的,这不是复制省略的示例。 (当然,这段只是C ++。)

如果初始化列表中的任何计算具有可见的副作用,则情况也是如此。

并且不言而喻,如果任何子对象的值不是常数,则需要在每个构造上完成该子对象的计算。

如果对象和所有子对象都是可以复制的,那么所有初始化列表计算都是常量,并且唯一的构造成本是从模板复制到对象中,如果有任何机会,编译器仍然无法执行优化可以同时看到对象的多个实时实例的地址。 例如,如果函数是递归的,并且对象的地址在某处使用(难以避免数组),那么可能会比较来自函数的不同递归调用的这些对象中的两个的地址。 他们必须比较不平等,因为它们实际上是单独的对象。 (而且,现在我想起来了,这个函数甚至不需要在多线程环境中递归。)

因此,希望将该对象优化为单个静态实例的编译器的举证责任非常高。 正如我所说的,很可能是给定的编译器实际上尝试执行该任务,但我绝对不会期望它。

编译器几乎肯定会做任何被认为是最优的东西,但很可能它会将它放在只读内存中并将你的局部变量转换为指向只读内存中数组的指针。 这假设您的数组等同于POD类型(或由POD类型组成的类;如果您的类执行非常重要的操作和/或修改其他内容,则编译器无法公平地执行此优化)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM