0%

C++ 对象模型 Construction Destruction Copy

对象构造

  1. 递归从左到右调用 virtual base class constructor
    • 存储 virtual base object 的 offset
  2. 递归从左到右调用 base class constructor (按照声明顺序,与 initialization list 顺序无关)
    • 如果在 initialization list 中有,传递参数
    • 如果 base class 是多重继承下的第二或之后的 base class,调整 this 指针
  3. 设定 virtual table pointer
  4. 按照 member 声明的顺序,如果 initialization list 中没有那么调用 default constructor
  • 在 copy operator 时考虑自赋值的情况 [[Chap.13 拷贝控制 #拷贝赋值函数]]
  • 在虚基类的情况下,如果某个 object 是 subject 那么不会调用 virtual base class 的构造函数(棱形继承的情况下,虚继承的两个中间基类不会调用基类的构造函数),final class 的构造函数会调用 virtual base class 的构造函数
  • 在构造函数中,调用 virtual function,调用的应该是当前构造中的实例 —— 所以 vptr 在 base class constructor 之后设定,但是在 initilization list 之前(避免有 virtual function 调用)

对象拷贝

  • 如果是菱形继承的情况,基类的拷贝可能会被多次调用

对象析构

  • 如果 base class/member object 没有析构函数,不需要析构函数
  1. destructor 函数本体
  2. 调用 member class objects 的 destructor(如果有)
  3. 重新设定 vptr,将其指向 base class 的 virtual table
  4. 调用 base class destructor
  5. 调用 virtual base class destructor

析构函数同构造函数,为了考虑虚继承的情况,可能会维护两份 destructor 实例

clang 中,会有两份:

  • complete object destructor: 作为 final class 调用的 destructor
  • base object destructor: 作为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    D1::~D1() [complete object destructor]:                             # @D1::~D1() [complete object destructor]
    push rbp
    mov rbp, rsp
    sub rsp, 16
    mov qword ptr [rbp - 8], rdi
    mov rdi, qword ptr [rbp - 8]
    mov qword ptr [rbp - 16], rdi # 8-byte Spill
    lea rsi, [rip + VTT for D1]
    call D1::~D1() [base object destructor]
    mov rdi, qword ptr [rbp - 16] # 8-byte Reload
    add rdi, 12
    call B::~B() [base object destructor]
    add rsp, 16
    pop rbp
    ret
    D1::~D1() [base object destructor]: # @D1::~D1() [base object destructor]
    push rbp
    mov rbp, rsp
    sub rsp, 16
    mov qword ptr [rbp - 8], rdi
    mov qword ptr [rbp - 16], rsi
    mov rax, qword ptr [rbp - 8]
    mov rcx, qword ptr [rbp - 16]
    mov rcx, qword ptr [rcx]
    mov qword ptr [rax], rcx
    mov rdi, qword ptr [rip + std::cout@GOTPCREL]
    lea rsi, [rip + .L.str.1]
    call std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@PLT
    jmp .LBB9_1
    .LBB9_1:
    add rsp, 16
    pop rbp
    ret
    mov rdi, rax
    call __clang_call_terminate

TODO

研究下构造函数