静态常量与重复调用函数中的常量
我只是想知道
void test()
{
const static int ABC = 12;
cout << ABC;
}
有什么不同
void test()
{
const int ABC = 12;
cout << ABC;
}
如果在程序执行时重复调用此函数 ?我的意思是,有性能差异吗?或者有什么理由让你更喜欢其中一种而不是另一种?
I'm just wondering how
void test()
{
const static int ABC = 12;
cout << ABC;
}
is different from
void test()
{
const int ABC = 12;
cout << ABC;
}
if this function is repeatedly called while the program is executing? What I mean is, is there any performance difference? Or is there a reason why you should prefer one over the other?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
有几个因素会影响答案:
所以答案是,在足够简单的情况下,编译器可以计算出它们并进行优化,这使得差异为零。在你的例子中几乎肯定是这种情况。
只要变量具有易于构造且成本低廉的类型,请选择非静态以避免缓存未命中。
如果构造该类型的成本很高,您可能希望使用
static
。当然,最后也是最重要的一点是:
不要相信我们的猜测。如果您担心性能,那么只有一个正确的做法:
There are a couple of things that affect the answer:
const
it will almost certainly be optimized out in any case. That means that the resulting code will most likely be the same.static
members are stored elsewhere which means less locality and probably a cache miss.So the answer is, in cases simple enough for the compiler to figure them out and optimize, it makes zero difference. In your example that would almost certainly be the case.
As long as the variable has a type that is easy and cheap to construct, prefer non-static to avoid the cache miss.
If the type is expensive to construct, you might want to use
static
.And of course, last, and most importantly of all:
Don't trust our guesswork. If you are concerned about performance, there is only one correct course of action:
理论上来说,前一种方法要好一点,因为它只实例化变量一次。
然而,编译器将简单地删除“const”行并替换为“cout << 12;”进入函数(显然,当在优化的情况下编译时)。
well theoretically the former method is a tiny bit better as it only insantiates the variable once.
However the compiler will simply remove either "const" line and substitute "cout << 12;" into the function (When compiled with optimisations on, obviously).
在第一次转换中,ABC 将仅在第一次函数调用时初始化一次。在第二种情况下,ABC 每次都会被初始化。如果 ABC 是带有构造函数的复杂类型,您会感觉到不同。它可以分配内存或初始化一些互斥体。对于 int 来说,实践中没有区别。
根据 C++03 标准 3.7.1/2:
In first cast ABC will be initialized only once, on first function call. In second case ABC will be initialized every time. You'll feel the difference if ABC is complex type with constructor. It could allocate memory or initialize some mutex. For int there is no difference in practice.
According to C++03 Standard 3.7.1/2:
这取决于编译器。
在嵌入式软件中,静态常量通常存储在闪存(即代码存储器)中,并且可以像普通变量一样直接访问,而不需要初始化。
相反,非静态 const 可能将其值存储在闪存中,但 const 本身将像变量一样在堆栈上创建,并像变量一样进行初始化。
如果这就是您的编译器处理这些情况的方式,那么 static const 会更有效,因为它既不需要堆栈分配也不需要初始化。
显然,非嵌入式编译器可能会以不同的方式处理这些场景。
It depends on the compiler.
In embedded software, a static const will typically be stored in flash (i.e. code memory), and will be accessed directly, like a normal variable, without any need for initialisation.
In contrast, a non-static const may have its value stored in flash, but the const itself will be created on the stack like a variable, and be initialised just like a variable.
If this is how your compiler handles these scenarios, then the static const is more efficient, as it requires neither stack allocation nor initialisation.
Obviously, these scenarios may be handled different by non-embedded compilers.
您还可以通过使用编译器的汇编器或类似以下在线实用程序来很好地了解编译器将执行的操作:https:// /godbolt.org 并查看生成的汇编代码。
这值得一看,因为这个问题很根本。
基于您的问题的示例,考虑本地与静态类型声明和实例化,查看基元与“复杂”(甚至不是非常):
编译器认识到它不必处理本地 const 复杂类型的任何内存链接,并且前四种情况的处理方式相同。看起来编译器并没有尝试探索复杂类型的相对简单性以及静态实例化中进一步简化的潜力。
由此产生的成本差异是比较巨大的。
使用gcc7.2和-O3优化编译的汇编代码:
You can also get a good idea of what the compiler will do by making use of your compiler's assembler or something like this online utility: https://godbolt.org and taking a look at the resulting assembly code.
This was worth a look, since the question is fundamental.
An example based on your question, looking at primitives vs "complex" (not even very) considering local vs static type declaration and instantiation:
The compiler recognizes that it doesn't have to deal with any memory linkage for local const complex types, and the first four cases are treated identically. It looks like the compiler doesn't try to explore the complex type's relative simplicity and potential for further simplification in the static instantiation.
The resulting cost difference is relatively huge.
The compiled assembly code using gcc7.2 with -O3 optimization:
对于基本类型,例如整数值,那么我会将静态的使用作为“过早的优化”,除非您已经做了一些基准测试并考虑了各种权衡(例如将静态初始化为非静态)零值通常需要表中的一个条目来指定加载代码时要设置的位置、大小和初始值)。
除非您使用指向 int 的指针并且在函数返回后取消引用它,否则您不需要 static - 让编译器进行优化。
如果在函数退出后取消引用指向该值的指针,那么我会将其归类为持久状态变量,并且最好在类或模块级别定义它以明确这一点。
For a basic type, such as an integer value, then I would pigeon hole the use of static as a "premature optimisation" unless you have done some benchmarking and taken into account the various trade offs (for example initialising a static to a non-zero value often requires an entry in a table to specify the position, size and initial value to be set when the code is loaded).
Unless you are taking a pointer to the int and it is dereferenced after your function returns then you don't need the static - let the compiler do the optimisation.
If a pointer to the value is dereferenced after your function has exited then I would class it as a persistent state variable and it would be good practice to define it at at the class or module level to make that clear.
我会选择第二个——它更具可读性。为什么不必要地添加一个关键字(静态),它实际上不会给阅读代码的人增加任何价值。
I would go with the second one - it is more readable. why unnecesarily add a keyword (static) that does not really add any value to someone reading the code.
static const 示例当然可以节省后续调用的执行时间,对于使用 static const 的复杂对象构造来说,速度要快得多,但我质疑是否需要将 ABC 限制在函数范围内,并引入从第一次调用到后续调用的函数行为变化来电。通常一个文件包含耦合的功能耦合函数,只需给出 ABC 文件范围并使用它即可。
The static const example certainly saves on execution time for subsequent calls, much faster for complex object construction to use static const, but I question the need to limit the ABC to function scope and introduce a variation in behaviour on the function from 1st call to following calls. Usually a file contains coupled functionally coupled functions, just give ABC file scope and be done with it.