constexpr
とpreprocessor macro
を使用して整数と文字列リテラルを定義することの違いを理解しようとしています。文字列リテラルと整数のC++ constexprとマクロ
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
を持っている機能の両方で観察することができ、次のアセンブリ出力を提供します
#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);
}
。私。リテラルとconstexp int
マクロ整数の間にフードの下目に見える違いは、存在しないconstexpr int
は、一方別のセクション_ZL10second_int
に格納されていても、文字列リテラルのために、我々は、命令movl $_ZL13second_string, %edi
とmovl $.LC0, %edi
マップがわかりそれぞれの文字列リテラルを2つの異なるセクションに分割します。
これら2つのセクションの違いは何ですか?実行可能ファイルが読み込まれると、メインメモリの別の部分にマップされますか?はいの場合、他の部分よりもアクセスが速いのですか?私はパフォーマンスのインパクトをプロファイルできますが、これらの2つのセクションの理論的な理由と違いを理解したいと思います。
で、同じです実行可能な領域が無駄になります。 'constexpr'は一意性を保証します。 –