• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 基于c++中的默认拷贝函数的使用详解

基于c++中的默认拷贝函数的使用详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c++拷贝构造函数,c++中拷贝构造函数,c++拷贝函数,c++浅拷贝,c++深拷贝和浅拷贝等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

《c++编程思想》上说一个类如果没有拷贝函数,那么编译器就会自动创建一个默认的拷贝函数。下面就让我们看一下真实的情况。

首先看一个简单的类X,这个类没有显示定义拷贝构造函数。

c++源码如下:

int main() {
    X x1;//先定义对象x1
    X x2 = x1;//将x1拷贝给x2
}
</div>
下面是其汇编代码:

; 7    : int main() {

    push    ebp
    mov    ebp, esp
    sub    esp, 16                    ; 为对象x1,x2预留16byte的栈空间

; 8    :     X x1;//先定义对象x1
; 9    :     X x2 = x1;//将x1拷贝给x2

    mov    eax, DWORD PTR _x1$[ebp];将x1的首地址里面的内容给寄存器eax,也就将x1中的成员变量i的值给eax
    mov    DWORD PTR _x2$[ebp], eax;将eax里面的值写入x2的首地址,也就是将eax里面的值写给x2的成员变量i
    mov    ecx, DWORD PTR _x1$[ebp+4];将偏移x1首地址4byte的内存里面的值给寄存器eax,也就是将x1中的成员变量j的值给ecx
    mov    DWORD PTR _x2$[ebp+4], ecx;将ecx里面的值写入偏移x2首地址4byte的内存里面,也就是将ecx里面的值写给x2的成员变量j

; 10   : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0
_main    ENDP
</div>
从汇编代码里面可以看出,根本没有函数被调用,所有的拷贝赋值都是通过寄存器与内存地址相互通信完成。和编译器提供默认构造函数一样,可以把这种情况看成是编译器提供了一个无用的拷贝构造函数。

那么,什么时候编译器才真正的提供默认拷贝构造函数,并且显示调用呢?

下面是一种情况,类X里面含有虚成员函数:

c++源码:

int main() {
    X x1;//先定义对象x1
    X x2 = x1;//将x1拷贝给x2
}
</div>
由于这里只讨论拷贝函数,所以只看主函数main和拷贝函数里面的汇编代码:

下面是主函数main里面的汇编代码:

; 9    : int main() {

    push    ebp
    mov    ebp, esp
    sub    esp, 24                    ; 由于引入了虚函数,每个类所占的空间编程12byte 成员变量i,j8byte vptr指针4byte 因此这里为x1 x2预留24byte

; 10   :     X x1;//先定义对象x1

    lea    ecx, DWORD PTR _x1$[ebp];获取x1的首地址,放入ecx,为调用构造函数的秘密参数传入,即this
    call    ??0X@@QAE@XZ;调用构造函数

; 11   :     X x2 = x1;//将x1拷贝给x2

    lea    eax, DWORD PTR _x1$[ebp];获取x1的首地址,放入寄存器eax
    push    eax;将eax压栈,作为拷贝构造函数的参数
    lea    ecx, DWORD PTR _x2$[ebp];获取x2的首地址,放入寄存器ecx,作为调用拷贝构造函数的秘密参数传入,即this
    call    ??0X@@QAE@ABV0@@Z;调用拷贝构造函数

; 12   : }

    lea    ecx, DWORD PTR _x2$[ebp];获取x2的首地址,放入ecx寄存器,作为调用析构函数传入的秘密参数,即this
    call    ??1X@@UAE@XZ                ; 调用析构函数
    lea    ecx, DWORD PTR _x1$[ebp];获取x1的首地址,放入ecx寄存器,作为调用析构函数传入的秘密参数,即this
                                ;析构的顺序与构建的顺序相反
    call    ??1X@@UAE@XZ                ; 调用析构函数
    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0
_main    ENDP
</div>
可以看到,编译器为类X提供了默认的拷贝构造函数(非无用的默认拷贝构造函数),并且显示调用。

由于一个类继承自虚基类或者继承自有虚函数成员的基类,使得它本身也含有虚函数成员,因此也就属于上一种情形。所以编译器在这种情况下,也会提供非无用的默认拷贝构造函数,并且能够显示调用。

下面是第二种情形,类X继承自类Y,类Y有显示定义的拷贝构造函数,而类没有提供拷贝构造函数:

下面是c++源码:


int main() {
    X x1;//先定义对象x1
    X x2 = x1;//将x1拷贝给x2
}
</div>
下面是mian函数汇编代码:

    push    ebp
    mov    ebp, esp
    sub    esp, 24                    ; 为x1 x2预留24byte空间

; 17   :     X x1;//先定义对象x1

    lea    ecx, DWORD PTR _x1$[ebp];获取x1的首地址,作为隐含参数传递给构造函数
    call    ??0X@@QAE@XZ;//调用编译器为类X提供的默认构造函数

; 18   :     X x2 = x1;//将x1拷贝给x2

    lea    eax, DWORD PTR _x1$[ebp];获取x1的首地址,传给寄存器eax
    push    eax;将eax压栈,作为调用类X的拷贝构造函数的参数
&n

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 深入理解C/C++中的写时拷贝
  • C++ 构造函数中使用new时注意事项
  • C++基础教程之指针拷贝详解
  • C++ 赋值构造函数注意点介绍
  • c++ 构造函数中调用虚函数的实现方法
  • C++ 类的构造函数详解及实例
  • C++聚合关系类的构造函数的调用顺序详解
  • 解析C++中构造函数的默认参数和构造函数的重载
  • 深入讲解C++中的构造函数
  • C++中构造函数重载

相关文章

  • 2017-05-28基于C++语言实现机动车违章处罚管理系统
  • 2017-05-28C++ 如何用cout输出hex,oct,dec的解决方法
  • 2017-05-28C++获取多浏览器上网历史记录示例代码(支持获取IE/Chrome/FireFox)
  • 2017-11-18使用opencv把图片拼接成视频
  • 2017-05-28c++实现的常见缓存算法和LRU
  • 2017-05-28C++中的Lambda表达式详解
  • 2017-05-28简介C++编程中的运算符重载
  • 2017-05-28八皇后问题实现代码分享
  • 2017-05-28C语言中变量与其内存地址对应的入门知识简单讲解
  • 2017-05-28简单讲解C语言中宏的定义与使用

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C语言 设计模式之访问者模式
    • c语言网络编程-标准步骤(改进版)
    • C++数据结构与算法之判断一个链表是否为回文结构的方法
    • C语言中的const,free用法详解
    • 原码, 反码与补码基础知识详细介绍
    • 利用C++的基本算法实现十个数排序
    • C语言打印华氏-摄氏温度对照表的方法
    • C语言实现的一个万年历小程序
    • C语言之实现控制台光标随意移动的实例代码
    • c++实现加载so动态库中的资源

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有