【发布时间】:2019-08-29 15:18:13
【问题描述】:
这是一个使用虚拟基类的简单继承(编译器资源管理器上的代码 available)。
class B {
public:
int i = 1;
};
class D : virtual public B {
public:
int j = 2;
};
void Assign(B *b) {
b->i = 2;
}
int main() {
B *b = new D();
Assign(b);
return 0;
}
main() 函数的汇编列表如下所示:
09 main: # @main
10 push rbp
11 mov rbp, rsp
12 sub rsp, 32
13 mov eax, 16
14 mov edi, eax
15 mov dword ptr [rbp - 4], 0
16 call operator new(unsigned long)
17 xor esi, esi
18 mov ecx, 16
19 mov edx, ecx
20 mov rdi, rax
21 mov qword ptr [rbp - 24], rax # 8-byte Spill
22 call memset
23 mov rdi, qword ptr [rbp - 24] # 8-byte Reload
24 call D::D() [complete object constructor]
25 xor ecx, ecx
26 mov eax, ecx
27 mov rdx, qword ptr [rbp - 24] # 8-byte Reload
28 cmp rdx, 0
29 mov qword ptr [rbp - 32], rax # 8-byte Spill
30 je .LBB1_2
31 mov rax, qword ptr [rbp - 24] # 8-byte Reload
32 mov rcx, qword ptr [rax]
33 mov rcx, qword ptr [rcx - 24]
34 add rax, rcx
35 mov qword ptr [rbp - 32], rax # 8-byte Spill
36 .LBB1_2:
37 mov rax, qword ptr [rbp - 32] # 8-byte Reload
38 mov qword ptr [rbp - 16], rax
39 mov rdi, qword ptr [rbp - 16]
40 call Assign(B*)
41 xor eax, eax
42 add rsp, 32
43 pop rbp
44 ret
汇编第27-38行的作用是什么?
第 29 行 rax 的值是多少?
为什么会有分支语句?
【问题讨论】:
-
你还能用
-Og得到类似的代码吗?-O0调试模式一团糟。 IDK 如果 gcc 会在-O0进行推测性去虚拟化,但它可能会。 -
提示:注意“vtable for D”符号,第一个成员!
-
@curiousguy 你是什么意思?
-
@chaosink 派生类的 vtable 的第一个字段包含编译器在此处需要的信息:“
vtable for D: .quad 12” 表示 base 位于D基类的偏移 +12 处( lax) 派生最多的对象D中的子对象。 (在派生对象是其自身的子对象的情况下,用松散的子对象说起来更容易。)注意 vptr 不指向 vtable 的开头!按照历史惯例,vptr[0]是第一个虚函数(如果有的话,或者虚函数数组的末尾)。偏移量为负偏移量 WRT vptr。
标签: c++ assembly constructor x86 virtual-inheritance