“static const”、“#define”和“enum”在性能和内存使用方面的区别
Posted
技术标签:
【中文标题】“static const”、“#define”和“enum”在性能和内存使用方面的区别【英文标题】:Difference between “static const”, “#define”, and “enum” in performance and memory usage aspects 【发布时间】:2014-01-23 17:28:35 【问题描述】:由于#define
语句的内联,可能存在任何问题。
我知道答案可能取决于编译器,那么假设 GCC。
about C 和 about C++ 已经有类似的问题,但更多的是关于使用方面的问题。
【问题讨论】:
请举例说明您所询问的值类型。既然你提到enum
,我猜是整数数字常量?
@πάνταῥεῖ 我问的是一般情况 - 关于所有可能类型的常量:数字、字符串文字、数组......
所以要点是不要使用#define 在“现代”C++ 中定义整数常量。如果它确实是一个数字,请使用 static const。如果它确实是一个可枚举的值,请使用 enum。不要担心性能和内存使用:相信你的编译器,除非它真的非常关键,在这种情况下相信你的编译器,但要检查以确保。
【参考方案1】:
在给定基本优化的情况下,编译器会以同样的方式对待它们。 检查起来相当容易 - 考虑以下 c 代码:
#define a 1
static const int b = 2;
typedef enum FOUR = 4 enum_t;
int main()
enum_t c = FOUR;
printf("%d\n",a);
printf("%d\n",b);
printf("%d\n",c);
return 0;
用 gcc -O3 编译:
0000000000400410 <main>:
400410: 48 83 ec 08 sub $0x8,%rsp
400414: be 01 00 00 00 mov $0x1,%esi
400419: bf 2c 06 40 00 mov $0x40062c,%edi
40041e: 31 c0 xor %eax,%eax
400420: e8 cb ff ff ff callq 4003f0 <printf@plt>
400425: be 02 00 00 00 mov $0x2,%esi
40042a: bf 2c 06 40 00 mov $0x40062c,%edi
40042f: 31 c0 xor %eax,%eax
400431: e8 ba ff ff ff callq 4003f0 <printf@plt>
400436: be 04 00 00 00 mov $0x4,%esi
40043b: bf 2c 06 40 00 mov $0x40062c,%edi
400440: 31 c0 xor %eax,%eax
400442: e8 a9 ff ff ff callq 4003f0 <printf@plt>
完全相同的汇编代码,因此 - 完全相同的性能和内存使用。
编辑:正如 Damon 在 cmets 中所说,可能存在一些极端情况,例如复杂的非文字,但这有点超出了问题的范围。
【讨论】:
有趣的大写选择:一个小写的宏和一个全部大写的枚举:) 感谢您的回答,但如果这些常量有多种用途,程序集表示不会改变吗? @user3075942:会有更多的代码,但是如果你只使用值,编译器会在调用的地方替换它。为什么变量的 1 次或 100 次使用会发生变化? 至于字符串文字 - 你会发现将这种情况与enum
进行比较会更复杂,但这并不会改变基本事实 - 编译器将所有这些都视为值,并且可以优化您可能认为他们持有的任何类型的临时存储。因此,它处理一种与另一种不同的常量是没有意义的(更不用说编译器甚至看不到#define
)
不幸的是,对于 许多 非整数文字情况,“相同”不是真的。例如,您可能期望 static const&
也可以进行微不足道的优化,但事实并非如此。例如。 struct fooint bar;; static const& bar_ref = foo.bar;
的开销肯定比 #define bar_ref foo.bar
多。 (是的,确实有需要这种可憎的情况。不要问。)【参考方案2】:
当用作常量表达式时,性能没有差异。如果用作左值,static const
将需要定义(内存)和访问(cpu)。
【讨论】:
以上是关于“static const”、“#define”和“enum”在性能和内存使用方面的区别的主要内容,如果未能解决你的问题,请参考以下文章