繁体   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