从汇编看c++中的默认构造函数

发表于:2013-5-20 10:05

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:chaoguo1234    来源:51Testing软件测试网采编

  c++中,如果为一个类没有明确定义一个构造函数,那么,编译器就会自动合成一个默认的构造函数。下面,通过汇编程序,来看一下其真实情况。

  c++中的源程序:

class X {
private:
    int i;
};

int main() {
    X x;
}

  上面的类X没有定义构造函数,仅仅有一个int i。

  下面为其汇编程序:

; 7    : int main() {

    push    ebp;ebp为一个寄存器,总是指向一个函数调用堆栈的栈底,作为基址,用偏移量来访问该调用栈上的变量,但这里没有任何变量要访问,因此不起作用
    mov    ebp, esp;这两句的作用是为了保存调用main之前堆栈的基址ebp的值,并将ebp指向main调用栈的栈底
    push    ecx;将寄存器ecx的值压栈, 栈顶指针esp向前移动4byte
               ;这句的作用,为即将要创建的对象预留了4byte的空间,并向里面写入ecx的值

; 8    :     X x;
; 9    : }

    xor    eax, eax;eax也是一个寄存器,这里不起作用
    mov    esp, ebp;将栈顶指针移动到push ecx前的位置,即释放了4byte的空间
    pop    ebp;恢复基址到main调用之前的状态
    ret    0;函数返回

  通过汇编发现,通过push ecx,编译器将堆栈栈顶移动4byte,并将寄存器的ecx的值写入,类X只含有一个int,大小刚好为4byte,因此这一句可以看成是为对象x分配空间。而接下来并没有任何函数的调用,来对这一块区域进行适当的初始化。所以,在没有明确定义一个构造函数的时候,不会有任何的初始化操作。

  这种情况下,在《深度探索c++对象模型》中,认为编译器只合成了一个无用的默认构造函数。

  下面再看一段c++程序:

class X {
private:
    int i;
    int j;//增加一个成员变量int j
};

int main() {
    X x;
}

  与上面相比,在类X里面增加了一个成员变量int j,类的大小变为8字节。

  下面为对应汇编码:

; 8    : int main() {

    push    ebp
    mov    ebp, esp
    sub    esp, 8; 栈顶指针移动8byte,刚好等于类X的大小

; 9    :     X x;
; 10   : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0

  从汇编码看出,通过sub esp,8指令,堆栈确实留出了8byte的空间,刚好等于类X的大小,同样没有调用任何函数,来进行初始化操作。

  所以,综上所述,在一个类没有明确定义构造函数的时候,编译器不会有任何的函数调用来进行初始化操作,仅仅是移动栈顶留出对象所需空间,也就是说,这种情况下,编译器根本不会提供默认的构造函数。

51/512345>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号