Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;字符串文字与整数中的constexpr与宏_C++_C++11_Macros_Constexpr - Fatal编程技术网

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

C++ C++;字符串文字与整数中的constexpr与宏,c++,c++11,macros,constexpr,C++,C++11,Macros,Constexpr,我试图找出使用constexpr和预处理器宏来定义整数和字符串文本之间的区别 #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); p

我试图找出使用
constexpr
预处理器宏来定义整数和字符串文本之间的区别

#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
。即,即使
constepr int
存储在单独的部分
\u ZL10second\u int
中,宏整数文本和
constepr int
之间在引擎盖下没有明显的差异

另一方面,对于字符串文本,我们看到指令
movl$\u ZL13second\u string,%edi
movl$.LC0,%edi
将它们各自的字符串文本映射到两个不同的部分


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

它们在功能上是等效的。请注意,这两种情况下的实际数据都是使用
.string
指令声明的。唯一不同的是标签名,其中一个实际上是C++对象(<代码>第二字符串> /COD>)有一个被损坏的名称,而宏只是具有一个通用的标签名。 如果在Linux的可执行文件上运行
objdump
,您会注意到这两个字符串都存储在
.rodata
部分:

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

原因之一是宏由预处理器处理,而constexpr由编译器处理。因此,constexpr不仅仅是字符串替换,它还可以检查类型

因此,即使程序集是相同的,在我看来,constexpr是一个更好的选择

如果您使用字符串
#define
两次,您必须依靠编译器来消除字符串文本的重复,否则会浪费可执行空间。
constepr
保证唯一性。