静态constexpr的编译器优化 给出以下C++代码: #include <stdio.h> static constexpr int x = 1; void testfn() { if (x == 2) printf("This is test.\n"); } int main() { for (int a = 0; a < 10; a++) testfn(); return 0; } #包括 静态constexpr int x=1; void testfn(){ 如果(x==2) printf(“这是测试。\n”); } int main(){ 对于(int a=0;a

静态constexpr的编译器优化 给出以下C++代码: #include <stdio.h> static constexpr int x = 1; void testfn() { if (x == 2) printf("This is test.\n"); } int main() { for (int a = 0; a < 10; a++) testfn(); return 0; } #包括 静态constexpr int x=1; void testfn(){ 如果(x==2) printf(“这是测试。\n”); } int main(){ 对于(int a=0;a,c++,static,compiler-optimization,constexpr,disassembly,C++,Static,Compiler Optimization,Constexpr,Disassembly,Visual Studio 2019生成以下调试生成程序集(使用接受答案的方法1查看:) intmain(){ 00EC1870推式ebp 00EC1871 mov ebp,esp 00EC1873子esp,0CCh 00EC1879推式ebx 00EC187A推式esi 00EC187B推式edi 00EC187C lea edi,[ebp-0CCh] 00EC1882 mov ecx,33小时 00EC1887 mov eax,0CCCH 00EC188C代表stos dword ptr e

Visual Studio 2019生成以下调试生成程序集(使用接受答案的方法1查看:)

intmain(){
00EC1870推式ebp
00EC1871 mov ebp,esp
00EC1873子esp,0CCh
00EC1879推式ebx
00EC187A推式esi
00EC187B推式edi
00EC187C lea edi,[ebp-0CCh]
00EC1882 mov ecx,33小时
00EC1887 mov eax,0CCCH
00EC188C代表stos dword ptr es:[edi]
00EC188E mov ecx,偏移量6D4A0457编译器如何处理_staticconstexpr@cpp(0ECC003h)
00EC1893呼叫@__CheckForDebuggerJustMyCode@4(0EC120Dh)
对于(int a=0;a<10;a++)
00EC1898 mov德沃德ptr[ebp-8],0
00EC189F jmp干管+3Ah(0EC18AAh)
00EC18A1 mov eax,dword ptr[ebp-8]
00EC18A4添加eax,1
00EC18A7 mov dword ptr[ebp-8],eax
00EC18AA cmp dword ptr[ebp-8],0Ah
00EC18AE jge干管+47小时(0EC18B7h)
testfn();
00EC18B0呼叫测试FN(0EC135Ch)
00EC18B5 jmp干管+31小时(0EC18A1h)
返回0;
00EC18B7异或eax,eax
}
从程序集中可以看出,可能是因为这是一个调试版本,所以在
main
中有对
for
循环和
testfn
的无意义引用。我希望他们在汇编代码中根本不会发现任何内容,因为
testfn
中的
printf
永远不会被命中,因为
static constexpr int x=1

我有两个问题:

(1) 也许在发布版本中,
for
循环被优化掉了。我怎么检查这个?即使使用在处指定的方法2,查看版本生成程序集代码对我也不起作用。根本不会生成包含程序集代码的文件


(2) 在使用
静态constexpr int/double/char
而不是
#define
时,在什么情况下可以保证前者不涉及任何不必要的开销(运行时计算/评估)
#define
,尽管受到很多诽谤,但在这方面似乎比static constexpr提供了更大的保证。

这里的问题是,您正在使用调试版本编译代码。如果您想要asm中的健全性,请改为编译为发行版。问题在于,调试器用于帮助确认底层代码的逻辑。底层代码的逻辑是它应该调用testfn()10次。因此,您应该能够在该方法上放置断点,并在执行过程中的正确点命中它。在发布版本中,这个断点永远不会被击中(因为它会被优化掉)

然而,在您的例子中,说constexpr被忽略是完全不正确的。您可能会注意到,在生成的asm中没有对printf()的调用,因此编译器已正确标识if(x==2)永远不可能为true,并已将其删除。但是,如果编译器完全删除了对testfn()的调用,断点将永远不会被命中,调试器基本上是无用的


不要看调试生成的输出,想象它告诉您有关代码或编译器的任何有用信息。您应该期望代码被故意去优化

这里的问题是您正在使用调试版本编译代码。如果您想要asm中的健全性,请改为编译为发行版。问题在于,调试器用于帮助确认底层代码的逻辑。底层代码的逻辑是它应该调用testfn()10次。因此,您应该能够在该方法上放置断点,并在执行过程中的正确点命中它。在发布版本中,这个断点永远不会被击中(因为它会被优化掉)

然而,在您的例子中,说constexpr被忽略是完全不正确的。您可能会注意到,在生成的asm中没有对printf()的调用,因此编译器已正确标识if(x==2)永远不可能为true,并已将其删除。但是,如果编译器完全删除了对testfn()的调用,断点将永远不会被命中,调试器基本上是无用的


不要看调试生成的输出,想象它告诉您有关代码或编译器的任何有用信息。您应该期望代码被故意去优化

检查这些东西非常有用。您可以添加两个编译器(都是VC++编译器),并使用不同的优化标志来立即查看生成代码中的差异。。请注意,
main
在发布版本中已完全优化。@user703016谢谢。有没有办法在VisualStudioIDE中查看发布版本程序集输出?检查这些东西非常有用。您可以添加两个编译器(都是VC++编译器),并使用不同的优化标志来立即查看生成代码中的差异。。请注意,
main
在发布版本中已完全优化。@user703016谢谢。有没有一种方法可以在Visual Studio IDE中查看发布版本程序集输出?这是正确的,调试代码最重要的一点是,您可以使用调试器逐步完成它,并查看代码行的功能。如果您尝试在发布版本中执行此操作,其中许多行已经过优化,那么您会发现调试器会跳到识别您自己的程序时出现问题,并且,如前所述,您将无法将断点放置在您想要的一半位置。我同意调试版本忠实于C++代码的必要性。有没有办法查看实际版本
int main() {
00EC1870  push        ebp  
00EC1871  mov         ebp,esp  
00EC1873  sub         esp,0CCh  
00EC1879  push        ebx  
00EC187A  push        esi  
00EC187B  push        edi  
00EC187C  lea         edi,[ebp-0CCh]  
00EC1882  mov         ecx,33h  
00EC1887  mov         eax,0CCCCCCCCh  
00EC188C  rep stos    dword ptr es:[edi]  
00EC188E  mov         ecx,offset _6D4A0457_how_compiler_treats_staticconstexpr@cpp (0ECC003h)  
00EC1893  call        @__CheckForDebuggerJustMyCode@4 (0EC120Dh)  
    for (int a = 0; a < 10; a++)
00EC1898  mov         dword ptr [ebp-8],0  
00EC189F  jmp         main+3Ah (0EC18AAh)  
00EC18A1  mov         eax,dword ptr [ebp-8]  
00EC18A4  add         eax,1  
00EC18A7  mov         dword ptr [ebp-8],eax  
00EC18AA  cmp         dword ptr [ebp-8],0Ah  
00EC18AE  jge         main+47h (0EC18B7h)  
        testfn();
00EC18B0  call        testfn (0EC135Ch)  
00EC18B5  jmp         main+31h (0EC18A1h)  
    return 0;
00EC18B7  xor         eax,eax  
}