C ++ constexpr vs字符串文字与整数中的宏

时间:2016-11-04 08:24:54

标签: c++ c++11 macros constexpr

我试图找出差异&#34;引擎盖下&#34;在使用try { InitializationValues iv = new InitializationValues(NSS_JSS_Utils.getFireFoxProfilePath()); iv.installJSSProvider = false; CryptoManager.initialize(iv); cm = CryptoManager.getInstance(); } catch (KeyDatabaseException | CertDatabaseException | GeneralSecurityException | NotInitializedException e) { e.printStackTrace(); } catch (AlreadyInitializedException e) { cm = CryptoManager.getInstance(); } CustomPasswordCallback pcb = new CustomPasswordCallback(); cm.setPasswordCallback(pcb); Enumeration< ? > emModules = cm.getModules(); constexpr来定义整数和字符串文字之间。

preprocessor macro

在使用#define FIRST_STRING "first_stringer" constexpr char second_string[] = "second_stringer"; #define FIRST_INT 1234 constexpr int second_int = 12345; int main () { printf("%s\n", second_string); printf("%s\n", FIRST_STRING); printf("%d\n", FIRST_INT); printf("%d\n", second_int); return 0; } void hello() { printf("%s\n", second_string); printf("%s\n", FIRST_STRING); printf("%d\n", FIRST_INT); printf("%d\n", second_int); }

编译时提供以下程序集输出
g++ -S main.cpp -std=c++11

在检查汇编代码时,我们可以在两个函数中观察到指令 .file "main.cpp" .section .rodata .LC0: .string "first_stringer" .LC1: .string "%d\n" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $_ZL13second_string, %edi call puts movl $.LC0, %edi call puts movl $1234, %esi movl $.LC1, %edi movl $0, %eax call printf movl $12345, %esi movl $.LC1, %edi movl $0, %eax call printf movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .globl _Z5hellov .type _Z5hellov, @function _Z5hellov: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $_ZL13second_string, %edi call puts movl $.LC0, %edi call puts movl $1234, %esi movl $.LC1, %edi movl $0, %eax call printf movl $12345, %esi movl $.LC1, %edi movl $0, %eax call printf popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size _Z5hellov, .-_Z5hellov .section .rodata .align 16 .type _ZL13second_string, @object .size _ZL13second_string, 16 _ZL13second_string: .string "second_stringer" .align 4 .type _ZL10second_int, @object .size _ZL10second_int, 4 _ZL10second_int: .long 12345 .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4" .section .note.GNU-stack,"",@progbits movl $1234, %esi。即即使movl $12345, %esi存储在单独的部分constexp int

中,宏整数字面值与constexpr int之间也没有明显差异。

另一方面,对于字符串文字,我们看到指令_ZL10second_intmovl $_ZL13second_string, %edi将它们各自的字符串文字映射到两个不同的部分。

这两个部分有什么区别?加载可执行文件后,它们是否映射到主内存的不同部分?如果是的话,访问速度比另一部分快一部分吗?我知道我可以描述性能影响,但我想了解这两个部分之间的理论原因和区别。

2 个答案:

答案 0 :(得分:3)

这些在功能上是等同的。请注意,两种情况下的实际数据都是使用.string指令声明的。唯一的区别在于标签名称,其中实际上是C ++对象的那个(second_string)具有错位名称,而宏只有一个通用标签名称。

如果您在Linux上的可执行文件上运行objdump,您会注意到这两个字符串都存储在.rodata部分中:

String dump of section '.rodata':
  [     4]  %s^J
  [     8]  first_stringer
  [    17]  %d^J
  [    20]  second_stringer

答案 1 :(得分:2)

原因是宏由预处理器处理,但constexpr由编译器处理。因此,constexpr不仅仅是字符串替换,例如它会检查类型。

所以即使是组装也是一样的,从我的角度来看,constexpr是一个更好的选择