为什么构造函数"return"这个指针?

why constructors "return" this pointer?

本文关键字:指针 return 构造函数 为什么      更新时间:2023-10-16

我注意到构造函数在返回之前会将this移动到eax。这是一个返回值还是其他什么?

class CTest {
    int val_;
public:
    CTest() {
0093F700  push        ebp  
0093F701  mov         ebp,esp  
0093F703  sub         esp,0CCh  
0093F709  push        ebx  
0093F70A  push        esi  
0093F70B  push        edi  
0093F70C  push        ecx  
0093F70D  lea         edi,[ebp-0CCh]  
0093F713  mov         ecx,33h  
0093F718  mov         eax,0CCCCCCCCh  
0093F71D  rep stos    dword ptr es:[edi]  
0093F71F  pop         ecx  
0093F720  mov         dword ptr [this],ecx  
        val_ = 1;
0093F723  mov         eax,dword ptr [this]  
0093F726  mov         dword ptr [eax],1  
    }
0093F72C  mov         eax,dword ptr [this]  
0093F72F  pop         edi  
0093F730  pop         esi  
0093F731  pop         ebx  
0093F732  mov         esp,ebp  
0093F734  pop         ebp  
0093F735  ret  

VS2012调试模式

<小时>

我发现new会使用它的"返回值"。看起来像if(operator new() == 0) return 0; else return constructor();

class CTest {
    int val_;
public:
    CTest() {
        val_ = 1;
        __asm {
            mov         eax, 0x12345678
            pop         edi  
            pop         esi  
            pop         ebx  
            mov         esp,ebp  
            pop         ebp  
            ret  
        }
    }
};
int main() {
    CTest *test = new CTest;    // test == 0x12345678
    return 0;
}

您的第二个问题与第一个问题不一致。如果constructor()正在生成条件结果,new如何使用if ( operator new() == 0 ) return 0; else return constructor();

无论如何…

  1. 编译器对寄存器的处理是编译器的事务。寄存器往往保存任何立即有用的信息,如果编译器在编写时相信每次使用构造函数时都会立即使用对象,那么它可以合理地选择将this放在寄存器中。

    ABI可能需要构造函数来做这件事,但我对此表示怀疑。无论如何,这样的协议只适用于从库导出的东西,而不是严格地在程序中。

  2. 在继续初始化对象之前,任何new表达式都会对照0检查operator new的结果。operator new可以通过返回nullptr(或NULL等)来发出故障信号

    这实际上可能是放置新表达式的一个问题,因为它代表了不可避免的运行时开销,因为给定的指针通常是非null的。

这可以是一个设计上的功能,在C++和其他语言中,返回对给定实例的引用可以更"惯用"地使用对象本身提供的功能,简而言之,它是命名参数Idiom。

但这只是一个选项,有时它可能很有用,尤其是如果您能够以一种只"执行操作"而不需要传递大量参数的方式来设计库,则方法调用链保持可读性。