隐式编译器创建的默认构造函数是否可以有多个 null 主体?

Hor*_*ace -1 c++ x86 winapi constructor default-constructor

隐式编译器创建的默认构造函数是否可以有多个 null 主体?根据IBM的网站,答案是:不。

我有这个项目有点难倒我:

这是声明一个名为 StackWalkerToConsole 的类的实例,没有定义默认构造函数的地方:

void func5()
{
  StackWalkerToConsole sw;
  ...
}
Run Code Online (Sandbox Code Playgroud)

这会以某种方式导致其父类的用户定义构造函数之一被调用:

StackWalker::StackWalker(int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess)
{
  // The function has a body, I just removed it for clarity's sake.
  ...
}
Run Code Online (Sandbox Code Playgroud)

因此,我在这个构造函数上放置了一个断点,并使用调用堆栈查看了 StackWalkerToConsole 的默认构造函数。由于源码中没有定义,所以只能看它的反汇编:

StackWalker_VC2017.exe!StackWalkerToConsole::StackWalkerToConsole(void):
0000000140008210  mov         qword ptr [rsp+8],rcx  
0000000140008215  push        rdi  
0000000140008216  sub         rsp,40h  
000000014000821A  call        qword ptr [__imp_GetCurrentProcess (014012E060h)]  
0000000140008220  mov         qword ptr [rsp+30h],rax  
0000000140008225  call        qword ptr [__imp_GetCurrentProcessId (014012E068h)]  
000000014000822B  mov         rcx,qword ptr [rsp+30h]  
0000000140008230  mov         qword ptr [rsp+20h],rcx  
0000000140008235  mov         r9d,eax  
0000000140008238  xor         r8d,r8d  
000000014000823B  mov         edx,3Fh  
0000000140008240  mov         rcx,qword ptr [this]
  
0000000140008245  call        StackWalker::StackWalker (0140002F1Dh)  

000000014000824A  mov         rax,qword ptr [this]  
000000014000824F  lea         rcx,[StackWalkerToConsole::`vftable' (01400ED6C0h)]  
0000000140008256  mov         qword ptr [rax],rcx  
0000000140008259  mov         rax,qword ptr [this]  
000000014000825E  add         rsp,40h  
0000000140008262  pop         rdi 
Run Code Online (Sandbox Code Playgroud)

这个编译器定义的构造函数调用 2 个 WinApi 函数:GetCurrentProcess 和 GetCurrentProcessId,并调用 StackWalker 的用户定义构造函数。

有人知道为什么吗?我应该提到,父类 StackWalker 也没有任何用户定义的默认构造函数。

如果需要更多信息,我很乐意提供。感谢您阅读本文。

编辑:这是代码的 github:这是一个小项目,只有 1 个 cpp 文件和 1 个 main.cpp 文件来测试它。我假设没有人有时间和精力来阅读代码,但将其放在这里以防万一。

在这篇文章中,我引用了main.cpp 中的第 41 行和StackWalker.cpp 中的第 929 行

Art*_*yer 7

您引用的课程:

class StackWalkerToConsole : public StackWalker
{
protected:
  virtual void OnOutput(LPCSTR szText) { printf("%s", szText); }
};
Run Code Online (Sandbox Code Playgroud)

有一个隐式声明的默认构造函数,看起来类似于:

StackWalkerToConsole::StackWalkerToConsole() : StackWalker() {}
Run Code Online (Sandbox Code Playgroud)

它调用StackWalker 的构造函数

  StackWalker(int    options = OptionsAll,
              LPCSTR szSymPath = NULL,
              DWORD  dwProcessId = GetCurrentProcessId(),
              HANDLE hProcess = GetCurrentProcess());
Run Code Online (Sandbox Code Playgroud)

StackWalker 确实有一个用户定义的默认构造函数,它可以用零参数调用)

因此,虽然 的默认构造函数没有主体StackWalkerToConsole,但它的基类会使用默认参数进行初始化StackWalker(OptionsAll, NULL, GetCurrentProcessId(), GetCurrentProcess()),并且 StackWalker 构造函数的主体会运行。