[英]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
可以在编译时计算(已知, I
是ItType::in
或ItType::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.