問題のコードで未定義の動作を呼び出していますconst
。constness をキャストすることによって宣言された変数を変更しようとすると、許可されません ( const 変数が実際に ではない変数への参照でない限りconst
)。
あなたの結果に対するもっともらしい、そして非常に可能性の高い説明は、コンパイラが の値がa
変更されるべきではないことa
を知っているということ5
です。すなわち。「ルックアップ」は最適化されています。
a
常に であると宣言されているのに、その値を読み取るために のアドレスを見るのはなぜ5
ですか?
コンパイラがスニペットをどのような命令に変換するかを見てみましょう
foo.cpp
void func (int)
{
/* ... */
}
int
main (int argc, char *argv[])
{
const int a = 10;
int * p = &const_cast<int&> (a);
*p = 20;
func (a);
}
main
によって与えられたの組み立て説明書g++ -S foo.cpp
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movl $10, -12(%rbp)
leaq -12(%rbp), %rax
movq %rax, -8(%rbp)
movq -8(%rbp), %rax # store the adress of `a` in %rax
movl $20, (%rax) # store 20 at the location pointed to by %rax (ie. &a)
movl $10, %edi # put 10 in register %edi (placeholder for first argument to function)
# # notice how the value is not read from `a`
# # but is a constant
call _Z4funci # call `func`
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
上で見たように、 の値20
は確かに( )のアドレスを含む%rax
場所に格納されているアドレスに置かれますが、への呼び出しの引数は定数( ) です。(%rax)
a
movl $20, (%rax)
void func (int)
10
movl $10, %edi
先に述べたように; コンパイラは、 の値が変化しないと想定し、が使用されるa
たびにメモリ位置を読み取る代わりに、a
代わりにそれを定数値に置き換えます10
。