簡體   English   中英

構造函數中的表達式的編譯時或運行時評估

[英]Compile-time or Run-time evaluation of expression in constructor

我有以下課程:

template<ItType I, LockType L>
class ArcItBase;

使用(其中一個)構造函數:

ArcItBase ( StableRootedDigraph& g_, Node const n_ ) noexcept :
  srd ( g_ ), 
  arc ( I == ItType::in 
           ? srd.nodes [ n_ ].head_in 
             : srd.nodes [ n_ ].head_out ) { }

問題是(我沒看到如何測試)是否將在編譯時或運行時確定arc的構造函數的表達式的值(Release,full optimization,clang-cl和VC14),鑒於I == ItType::in可以在編譯時計算(已知, IItType::inItType::out ),為true還是false?

在編譯時不知道ItType就不可能編譯代碼。

模板參數在編譯時計算,條件是核心常量表達式,標准參考是C ++ 11 5.19 / 2。

在對比的情況下,編譯器必須生成相當於的代碼

arc(true ? : )

如果你真的寫它會優化。 但是,條件的其余部分將不會被優化,因為您正在訪問看似非靜態成員的內容,並且無法將其評估為核心常量表達式。

但是,編譯器可能並不總是像我們期望的那樣工作,所以如果你真的想要測試它,你應該轉儲反匯編的目標文件

objdump -DS file.o

然后你可以更好地導航輸出。

另一種選擇是啟動調試器並檢查代碼。

不要忘記,即使在優化的情況下,您也可以始終擁有符號,例如

g++ -O3 -g -c foo.cpp

您將在下面找到玩具實施方案。 在第一種情況下,賦予arcbase構造函數的值稱為:

arcbase<true> a(10,9);

而在第二個中,給出了在編譯時無法知道的非const隨機值。

g++ --stc=c++11 -c -O3 -g編譯后,第一種情況創建:

Disassembly of section .text._ZN7arcbaseILb1EEC2Eii:

0000000000000000 <arcbase<true>::arcbase(int, int)>:
        srd isrd;

        arc iarc; 

        public:
        arcbase(int a , int b) : isrd(a,b) , iarc( I == true ? isrd.nodes.head_in : isrd.nodes.head_out ) {}
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
   c:   89 75 f4                mov    %esi,-0xc(%rbp)
   f:   89 55 f0                mov    %edx,-0x10(%rbp)
  12:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  16:   8b 55 f0                mov    -0x10(%rbp),%edx
  19:   8b 4d f4                mov    -0xc(%rbp),%ecx
  1c:   89 ce                   mov    %ecx,%esi
  1e:   48 89 c7                mov    %rax,%rdi
  21:   e8 00 00 00 00          callq  26 <arcbase<true>::arcbase(int, int)+0x26>
  26:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  2a:   8b 00                   mov    (%rax),%eax
  2c:   48 8b 55 f8             mov    -0x8(%rbp),%rdx
  30:   48 83 c2 08             add    $0x8,%rdx
  34:   89 c6                   mov    %eax,%esi
  36:   48 89 d7                mov    %rdx,%rdi
  39:   e8 00 00 00 00          callq  3e <arcbase<true>::arcbase(int, int)+0x3e>
  3e:   c9                      leaveq 
  3f:   c3                      retq  

而第二種情況:

Disassembly of section .text._ZN7arcbaseILb1EEC2Eii:

0000000000000000 <arcbase<true>::arcbase(int, int)>:
        srd isrd;

        arc iarc; 

        public:
        arcbase(int a , int b) : isrd(a,b) , iarc( I == true ? isrd.nodes.head_in : isrd.nodes.head_out ) {}
   0:   53                      push   %rbx
   1:   48 89 fb                mov    %rdi,%rbx
   4:   e8 00 00 00 00          callq  9 <arcbase<true>::arcbase(int, int)+0x9>
   9:   48 8d 7b 08             lea    0x8(%rbx),%rdi
   d:   8b 33                   mov    (%rbx),%esi
   f:   5b                      pop    %rbx
  10:   e9 00 00 00 00          jmpq   15 <arcbase<true>::arcbase(int, int)+0x15>

查看dissasembly,您應該注意到,即使在第一種情況下,10的值也不會直接傳遞給構造函數,而是僅放置在從哪里檢索的寄存器中。

這是gdb的輸出:

0x400910 <_ZN3arcC2Ei>                  mov    %esi,(%rdi)                                                      
0x400912 <_ZN3arcC2Ei+2>                retq                                                                    
0x400913                                nop                                                                     
0x400914                                nop                                                                     
0x400915                                nop                                                                     
0x400916                                nop                                                                     
0x400917                                nop                                                                     
0x400918                                nop                                                                     
0x400919                                nop                                                                     
0x40091a                                nop                                                                     
0x40091b                                nop                                                                     
0x40091c                                nop                                                                     
0x40091d                                nop                                                                     
0x40091e                                nop                                                                     
0x40091f                                nop                                                                     
0x400920 <_ZN7arcbaseILb1EEC2Eii>       push   %rbx                                                             
0x400921 <_ZN7arcbaseILb1EEC2Eii+1>     mov    %rdi,%rbx                                                        
0x400924 <_ZN7arcbaseILb1EEC2Eii+4>     callq  0x400900 <_ZN3srdC2Eii>                                          
0x400929 <_ZN7arcbaseILb1EEC2Eii+9>     lea    0x8(%rbx),%rdi                                                   
0x40092d <_ZN7arcbaseILb1EEC2Eii+13>    mov    (%rbx),%esi                                                      
0x40092f <_ZN7arcbaseILb1EEC2Eii+15>    pop    %rbx                                                             
0x400930 <_ZN7arcbaseILb1EEC2Eii+16>    jmpq   0x400910 <_ZN3arcC2Ei>

第二種情況的代碼是:

struct llist
{
  int head_in;
  int head_out;

  llist(int a , int b ) : head_in(a), head_out(b) {}
};

struct srd
{
  llist nodes;
  srd(int a, int b) : nodes(a,b) {}
};

struct arc
{
  int y;
  arc( int x):y(x) {}
};


template< bool I > class arcbase
{
  srd isrd;

  arc iarc;

  public:
  arcbase(int a , int b) : isrd(a,b) , iarc( I == true ? isrd.nodes.head_in : isrd.nodes.head_out ) {}

  void print()
  {
    std::cout << iarc.y << std::endl;
  }

};


int main(void)
{

  std::srand(time(0));

  volatile int a_ = std::rand()%100;
  volatile int b_ = std::rand()%4;

  arcbase<true> a(a_,b_);

  a.print();

  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM