【发布时间】:2020-09-08 07:17:22
【问题描述】:
我用 MSVC /O2 和 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
- 两个编译器都从
ir生成汇编代码,但不是从ip生成的(上面省略了main的代码)。请参阅godbolt。为什么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;
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
- 有了
-O0,为什么引用变量下面会有几个.quad i? -
-O2代码是从引用生成的,而不是从指针生成的。为什么会有这种差异?请参阅godbolt。
【问题讨论】:
-
你为什么期望相同的代码?你认为指针和引用是一回事吗?
-
@StephenM.Webb:我认为也有相似之处和不同之处,但在汇编代码中我从未看到它们之间有任何区别。因此,问题出现了:当前的差异是必要的还是只是在更复杂的实现中的疏忽?
-
不同的编译器生成不同的代码; 11 点的新闻。如果有多种方法可以生成导致相同结果的代码,C++ 标准将其留给实现来选择一种。对于将生成哪些实际指令,您没有保证,只有它们将实现原始源指定的行为(当然,除非存在未定义的行为,那么所有的赌注都没有了)。
-
在我看来,这确实像是编译器优化失败。可能是因为 constexpr 引用并没有真正意义,而且应该很少见。
-
"使用 -O0 为什么引用变量下有几个 .quad i ?" - 也许它使调试器更容易?毕竟,这是
-O0最关心的问题。
标签: c++ pointers reference code-generation constexpr