简体   繁体   English

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

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

Not sure if this has already been asked before. 不确定之前是否已经提出这个问题。 While answering this very simple question , I asked myself the following instead. 在回答这个非常简单的问题时 ,我问自己以下问题。 Consider this: 考虑一下:

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

Now in theory, local variables are recreated every time control reaches function, right? 现在理论上,每次控制到达功能时都会重新创建局部变量,对吧? Ie look at int i above - it's going to be recreated on the stack for sure. 即看上面的int i - 它肯定会在堆栈上重新创建。 What about the array above? 上面的数组怎么样? Can a compiler be as smart as to optimize its creation to occur only once, or do I need a static modifier here anyway? 编译器可以像智能一样优化其创建只发生一次,或者我还需要static修改器吗? What about if the array is not const ? 如果数组不是const怎么办? (OK, if it's not const , there probably i snot sense in creating it only once, since re-initialization to the default state may be required between calls due to modifications being made during function execution.) (好吧,如果它不是const ,那么在创建它时可能只有一次感觉,因为在函数执行期间进行修改时,可能需要在调用之间重新初始化为默认状态。)

Might sound like a basic question, but for some reason I still ponder. 可能听起来像一个基本问题,但出于某种原因,我仍然在思考。 Also, ignore the "why would you want to do this" - this is just a language question, not applied to a certain programming problem or design. 另外,忽略“你为什么要这样做” - 这只是一个语言问题,不适用于某个编程问题或设计。 I mean both C and C++ here. 我的意思是C和C ++。 Should there be differences between the two regarding this question, please outline those. 如果这两个问题存在差异,请概述这些问题。

There a two questions here, I think: 我想这里有两个问题:

  • Can a compiler optimize a non- static const object to be effectively static so that it is only created once; 编译器可以优化非static const对象进行有效static使得它不仅创造一次; and

  • Is it a reasonable expectation that a given compiler will do so. 给定的编译器是否会这样做是合理的期望。

I think the answer to the second question is "No", because I don't see the point of doing a huge amount of control flow analysis to save the programmer the trouble of typing the word static . 我认为第二个问题的答案是“否”,因为我没有看到进行大量控制流分析以保存程序员输入单词static的麻烦。 However, I've often been surprised what optimizations people spend their time writing (as opposed to the optimizations which I think they should be working on :-) ). 然而,我经常对人们花时间写作的优化感到惊讶(与认为他们应该进行的优化相反:-))。 All the same, I would strongly recommend using the word static if that's what you wanted. 同样,如果那就是你想要的,我强烈建议使用static这个词。

For the first question, there are circumstances under which the compiler could perform the optimization based on the "as-if" rule, but in very few cases would it work out. 对于第一个问题,在某些情况下,编译器可以根据“as-if”规则执行优化,但在极少数情况下会解决。

First of all, if any object or subobject in the initializer has a non-trivial constructor/destructor, then the construction/destruction is visible, and this is not an example of copy elision. 首先,如果初始化程序中的任何对象或子对象具有非平凡的构造函数/析构函数,则构造/销毁是可见的,这不是复制省略的示例。 (This paragraph is C++ only, of course.) (当然,这段只是C ++。)

The same would be true if any computation in the initializer list has visible side-effects. 如果初始化列表中的任何计算具有可见的副作用,则情况也是如此。

And it should go without saying that if any subobject's value is not constant, the computation of that subobject would need to be done on each construction. 并且不言而喻,如果任何子对象的值不是常数,则需要在每个构造上完成该子对象的计算。

If the object and all subobjects are trivially copyable, all the initializer-list computations are constant, and the only construction cost is that of copying from a template into the object, then the compiler still couldn't perform the optimization if there is any chance that the addresses of more than one live instance of the object might be simultaneously visible. 如果对象和所有子对象都是可以复制的,那么所有初始化列表计算都是常量,并且唯一的构造成本是从模板复制到对象中,如果有任何机会,编译器仍然无法执行优化可以同时看到对象的多个实时实例的地址。 For example, if the function were recursive, and the object's address was used somewhere (hard to avoid for an array), then there would be the possibility that the addresses of two of these objects from different recursive invocations of the function might be compared. 例如,如果函数是递归的,并且对象的地址在某处使用(难以避免数组),那么可能会比较来自函数的不同递归调用的这些对象中的两个的地址。 And they would have to compare unequal, since they are in fact separate objects. 他们必须比较不平等,因为它们实际上是单独的对象。 (And, now that I think of it, the function would not even need to be recursive in a multi-threaded environment.) (而且,现在我想起来了,这个函数甚至不需要在多线程环境中递归。)

So the burden of proof for a compiler wishing to optimize that object into a single static instance is quite high. 因此,希望将该对象优化为单个静态实例的编译器的举证责任非常高。 As I said, it may well be that a given compiler actually attempts to perform that task, but I definitely wouldn't expect it to. 正如我所说的,很可能是给定的编译器实际上尝试执行该任务,但我绝对不会期望它。

The compiler would almost certainly do whatever is deemed most optimal, but most likely it will have it in read-only memory and turn your local variable into a pointer that points to the array in read-only memory. 编译器几乎肯定会做任何被认为是最优的东西,但很可能它会将它放在只读内存中并将你的局部变量转换为指向只读内存中数组的指针。 This assumes your array is equivalent to a POD type (or a class composed of POD types; if your class does something non-trivial and/or modifies other things, there is no way the compiler can fairly do this optimization). 这假设您的数组等同于POD类型(或由POD类型组成的类;如果您的类执行非常重要的操作和/或修改其他内容,则编译器无法公平地执行此优化)。

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

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