我用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。 最佳答案
除了指令问题外,这只是链接:constexpr
表示const
(在变量本身上,而不是在其引用对象上,如果有的话),从而将internal linkage赋予您的指针。 (这是一种黑客,允许在C++ 17的内联变量之前的头文件中使用命名空间范围的命名常量;很遗憾,我们现在必须记住它。)由于没有其他翻译单元可以引用它们,因此无需发出符号;但是,这些引用可以在其他地方声明和使用:
extern int &ir;
void count() {++ir;}
因此,必须有附加此类用途的符号。
关于c++ - 为什么从constexpr引用生成的汇编代码与constexpr指针生成的汇编代码不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61938242/