C++ 为什么从constexpr引用生成的汇编代码与从constexpr指针生成的汇编代码不同?

C++ 为什么从constexpr引用生成的汇编代码与从constexpr指针生成的汇编代码不同?,c++,pointers,reference,code-generation,constexpr,C++,Pointers,Reference,Code Generation,Constexpr,我用MSVC/O2和clang编译了以下程序: int i; constexpr int& ir = i; constexpr int* ip = &i; int main() { ir = 1; *ip = 2; } 两个编译器都从ir生成汇编代码,但不是从ip(上面省略了main中的代码)。再见。为什么ir和ip不同?我了解到,汇编代码中的引用和指针是相同的 Gcc做了一件更奇怪的事情。我用gcc-O0和-O2编译了以下程序:

我用MSVC
/O2
和clang编译了以下程序:

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


int main()
{
    ir  = 1;
    *ip = 2;
}
  • 两个编译器都从
    ir
    生成汇编代码,但不是从
    ip
    (上面省略了
    main
    中的代码)。再见。为什么
    ir
    ip
    不同?我了解到,汇编代码中的引用和指针是相同的
Gcc做了一件更奇怪的事情。我用gcc
-O0
-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;
  • 使用
    -O0
    为什么参考变量下有几个
    .quad i
  • 使用
    -O2
    时,代码是从引用生成的,而不是从指针生成的。为什么会有这种差异?再见

除了指令问题,这只是链接:
constexpr
意味着
const
(在变量本身上,而不是它的引用,如果有的话),并因此提供给指针。(在C++17的内联变量之前,这是一种允许头文件中名称空间范围命名常量的黑客行为;不幸的是,我们现在必须记住它。)由于没有其他翻译单元可以引用它们,因此不需要为它们发出符号;但是,可以在其他地方声明和使用引用:

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

因此,必须有一个符号来附加这些用途。

为什么您希望使用相同的代码?你认为指针和引用是同一件事吗?@StephenM.Webb:我认为,它们也有相似之处和不同之处,但在汇编代码中,我从来没有看到它们之间有任何区别。因此,问题出现了:当前的差异是必要的还是只是compler实现中的疏忽?不同的编译器生成不同的代码;11点新闻。如果有多种方法生成代码,导致相同的结果,则C++标准将它留给实现来选择一个。您无法保证将生成什么实际指令,只能保证它们将实现原始源指定的行为(当然,除非存在未定义的行为,否则所有赌注都将被取消)。在我看来,这确实像是编译器优化失败。可能是因为constexpr引用没有真正的意义,应该非常罕见。“使用-O0时,为什么引用变量下面有几个.quad i?”-也许这会让调试器更容易一些?毕竟,这是
-O0
extern int&ir
的主要关注点,它没有链接到
constexpr int&ir=i。我得到了未解析的外部符号。因此我认为,后者毕竟有内在联系。它不能用于其他翻译单位。@Dr.Gut:它。我很惊讶,它与gcc一起工作。MSVC和clang都不起作用。我不明白,为什么。它确实有效。切换编译器时,我忘了将
def.cc
添加到编译中。如何创建指向wandbox程序的链接?@Dr.Gut:运行该程序时,输出窗口上方会出现一个共享链接。
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
extern int &ir;
void count() {++ir;}