简体   繁体   English

构造函数中的表达式的编译时或运行时评估

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

I have the following class: 我有以下课程:

template<ItType I, LockType L>
class ArcItBase;

with a (one of them) constructor: 使用(其中一个)构造函数:

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

The question is (which I don't see how to test) whether the value of the expression for the constructor of arc will be determined at compile-time or at run-time (Release, full optimization, clang-cl and VC14), given that I == ItType::in can be evaluated (is known, I is either ItType::in or ItType::out ) at compile-time to either true or false? 问题是(我没看到如何测试)是否将在编译时或运行时确定arc的构造函数的表达式的值(Release,full optimization,clang-cl和VC14),鉴于I == ItType::in可以在编译时计算(已知, IItType::inItType::out ),为true还是false?

It is not possible to have your code compiling without knowing the ItType at compile time. 在编译时不知道ItType就不可能编译代码。

The template parameter is evaluated at compile time and the conditional is a core constant expression, standard reference is C++11 5.19/2. 模板参数在编译时计算,条件是核心常量表达式,标准参考是C ++ 11 5.19 / 2。

In the contrasting case the compiler would have to generate code that is equivalent to 在对比的情况下,编译器必须生成相当于的代码

arc(true ? : )

Which if you would actually write it would be optimized. 如果你真的写它会优化。 However the rest of the conditional will not be optimized since you are accessing a what seems to be a non static member and cannot be evaluated as a core constant expression. 但是,条件的其余部分将不会被优化,因为您正在访问看似非静态成员的内容,并且无法将其评估为核心常量表达式。

However, compilers may not always work as we expect so if you would actually want to test this you should dump the disassembled object file 但是,编译器可能并不总是像我们期望的那样工作,所以如果你真的想要测试它,你应该转储反汇编的目标文件

objdump -DS file.o

and then you can better navigate the output. 然后你可以更好地导航输出。

Another option would be to launch the debugger and inspect the code. 另一种选择是启动调试器并检查代码。

Don't forget that you can always have your symbols even in case of optimizing, eg 不要忘记,即使在优化的情况下,您也可以始终拥有符号,例如

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

Below you will find a toy implementation . 您将在下面找到玩具实施方案。 In the first case values are given to the constructor of arcbase is called as: 在第一种情况下,赋予arcbase构造函数的值称为:

arcbase<true> a(10,9);

Whereas in the second it is given non const random values that cannot be known at compile time. 而在第二个中,给出了在编译时无法知道的非const随机值。

After compiling with g++ --stc=c++11 -c -O3 -g the first case creates: 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  

Whereas the second case: 而第二种情况:

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>

Looking at the dissasembly you should notice that even in the first case the value of 10 is not directly passed as is to the constructor, but instead only placed in the register from where is is retrieved. 查看dissasembly,您应该注意到,即使在第一种情况下,10的值也不会直接传递给构造函数,而是仅放置在从哪里检索的寄存器中。

Here is the output from gdb : 这是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>

The code for the second case is : 第二种情况的代码是:

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