10

我注意到构造函数将在返回之前移动thiseax。这是返回值还是别的什么?

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;
}
4

2 回答 2

1

您的第二个问题与您的第一个问题不同。如何new使用if ( operator new() == 0 ) return 0; else return constructor();ifconstructor()产生条件结果?

总之……</p>

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

    ABI 可能需要构造函数来执行此操作,但我怀疑是否有人这样做。无论如何,这样的协议只适用于从库中导出的东西,而不是严格地在程序中。

  2. 在继续初始化对象之前,任何new表达式都会检查operator new反对的结果。可能通过返回(或,等)来表示失败。0operator newnullptrNULL

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

于 2013-07-31T03:55:26.883 回答
0

这可以是设计的特性,在 C++ 和其他语言中,返回对给定实例的引用允许更“惯用”地使用对象本身提供的特性,简而言之,它是命名参数 Idiom

但这只是 1 个选项,它有时会很有用,特别是如果您能够以一种仅“采取行动”而无需传递大量参数的方式设计您的库,因此方法调用链保持可读性。

于 2013-07-31T05:46:37.017 回答