简体   繁体   中英

Why is different assembly code generated from a constexpr reference than a constexpr pointer?

I compiled the following program with MSVC /O2 and clang:

int            i;
constexpr int& ir = i;
constexpr int* ip = &i;


int main()
{
    ir  = 1;
    *ip = 2;
}
MSVC /O2                           clang
===========================        =============================================
int i DD 01H DUP (?) ; i           i:
_DATA SEGMENT                              .long   0                       # 0x0
int & ir DQ FLAT:int i ; ir
_DATA ENDS                         ir:
                                           .quad   i
  • Both compilers generate assembly code from ir , but not from ip (code from main is omitted above). See on godbolt . Why are ir and ip different? I learnt, that in assembly code references and pointers are the same.

Gcc does an even stranger thing. I compiled the following program with gcc -O0 and -O2 :

int            i;

constexpr int& ir1   = i;
constexpr int* ir1p1 = &i;

constexpr int& ir2   = i;
constexpr int* ir2p1 = &i;
constexpr int* ir2p2 = &i;

constexpr int& ir3   = i;
constexpr int* ir3p1 = &i;
constexpr int* ir3p2 = &i;
constexpr int* ir3p3 = &i;
gcc -O0            gcc -O2
=========          ==================
i:                 ir3:
  .zero 4                   .quad   i
ir1:               ir2:
  .quad i                   .quad   i
  .quad i          ir1:
ir2:                        .quad   i
  .quad i          i:
  .quad i                   .zero   4
  .quad i
ir3:
  .quad i
  .quad i
  .quad i
  .quad i
  • With -O0 why are there several .quad i 's under the reference variables?
  • With -O2 code is generated from references, but not from pointers. Why is this difference? See on godbolt .

Aside from the directives issue, this is just linkage : constexpr implies const (on the variable itself, not its referent, if any), and thereby gives internal linkage to your pointers. (This is a hack to allow namespace-scope named constants in header files prior to C++17's inline variables; it's unfortunate that we have to remember it now.) Since no other translation unit can refer to them, there's no need to emit symbols for them; the references, however, can be declared and used elsewhere:

extern int &ir;
void count() {++ir;}

and so there must be a symbol to which to attach such uses.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM