C++ 为什么从constexpr引用生成的汇编代码与从constexpr指针生成的汇编代码不同?
我用MSVCC++ 为什么从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编译了以下程序:
/O2
和clang编译了以下程序:
int i;
constexpr int& ir = i;
constexpr int* ip = &i;
int main()
{
ir = 1;
*ip = 2;
}
- 两个编译器都从
生成汇编代码,但不是从ir
(上面省略了ip
中的代码)。再见。为什么main
和ir
不同?我了解到,汇编代码中的引用和指针是相同的ip
-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;}