c++ - 将函数内的大变量声明为 `static` 在性能上有什么不同吗?

标签 c++ c static-members

不确定之前是否有人问过这个问题。在回答 this very simple question 时,我问自己以下内容。考虑一下:

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... */
}

现在理论上,每次控制达到功能时都会重新创建局部变量,对吗? IE。看看上面的 int i - 它肯定会在堆栈上重新创建。上面的数组呢?编译器能否聪明到优化它的创建只发生一次,还是我在这里需要一个 static 修饰符?如果数组不是 const 怎么办? (好吧,如果它不是 const,我可能只创建它一次就没有意义,因为由于在函数执行期间进行修改,调用之间可能需要重新初始化到默认状态。)

这听起来像是一个基本问题,但出于某种原因我仍在思考。另外,忽略“你为什么要这样做”——这只是一个语言问题,不适用于某个编程问题或设计。我在这里指的是 C 和 C++。如果两者在这个问题上有分歧,请概述。

最佳答案

我认为这里有两个问题:

  • 编译器可以优化非static const 对象使其有效地static 以便它只创建一次;和

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

我认为第二个问题的答案是“否”,因为我不明白进行大量控制流分析以节省程序员输入单词 static 的麻烦的意义>。然而,我经常对人们花时间编写的优化感到惊讶(而不是认为他们应该致力于的优化:-))。尽管如此,如果您需要的话,我强烈建议您使用 static 这个词。

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

首先,如果初始化器中的任何对象或子对象具有非平凡的构造函数/析构函数,那么构造/析构是可见的,这不是复制省略的例子。 (当然,本段仅适用于 C++。)

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

不言而喻,如果任何子对象的值不是常量,则需要在每次构造时对该子对象进行计算。

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

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

关于c++ - 将函数内的大变量声明为 `static` 在性能上有什么不同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35249932/

相关文章:

c++ - 封装ublas并重载对operator()的const引用

c++ - 下面的程序在 C++ 中如何工作?

c++ - 多级私有(private)和公共(public)继承 - 不寻常的访问

c++ - 如何强制初始化静态成员?

c++ - 静态数据成员的定义

c++ - C++初学者:为什么我的编译器根据我的循环返回 “name not found”?

c - 如何在 header 中使用静态函数并与 float 组进行比较

c - scanf() 将换行符保留在缓冲区中

c - 为什么在我的centos中打印三次 'hello'?

Java线程不共享静态数据