• 下面是C++中定义的深,浅拷贝

    • 当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
      (1)一个对象以值传递的方式传入函数体 
      (2)一个对象以值传递的方式从函数返回 
      (3)一个对象需要通过另外一个对象进行初始化。

      如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。

      自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

      浅拷贝和深拷贝

        在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。

        深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。下面举个深拷贝的例子。

    • 总结:有资源的重新分配:深拷贝;无:浅拷贝(直接的调用默认的构造函数实际上也是共享了一款数据的内存,两个对象都指向这块数据内存)
  • 下面是QT中的深浅拷贝,我觉得它的东西理解起来比较实用
    •   

      1.浅拷贝:

      浅拷贝就比如像引用类型

      浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉。

      2.深拷贝:

      而深拷贝就比如值类型。改变了数据的内存指向,内存分配发生改变。

      Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。

      3.隐式共享:

      隐式共享又叫做回写复制。当两个对象共享同一份数据时(通过浅拷贝实现数据块的共享),如果数据不改变,不进行数据的复制。而当某个对象需要改变数据时则执行深拷贝。

    • 实例:
      void MainWindow::on_pushButton_8_clicked()
      {
      QString str1="data";
      qDebug() << " String addr = " << &str1 <<", "<< str1.constData();
      QString str2=str1; //浅拷贝指向同一个数据块
      qDebug() << " String addr = " << &str2 <<", "<< str2.constData();
      str2[]='e'; //一次深拷贝,str2对象指向一个新的、不同于str1所指向的数据结构
      qDebug() << " String addr = " << &str2 <<", "<< str2.constData();
      str2[]='f'; //不会引起任何形式的拷贝,因为str2指向的数据结构没有被共享
      qDebug() << " String addr = " << &str2 <<", "<< str2.constData();
      str1=str2; //str1指向的数据结构将会从内存释放掉,str1对象指向str2所指向的数据结构
      qDebug() << " String addr = " << &str1 <<", "<< str1.constData();
      qDebug() << " String addr = " << &str2 <<", "<< str2.constData();
      }

      实测输出结果如下(括号内是我的分析):

      String addr = 0x28c798 , 0x14316660 (str2的指针地址,指向前面同一个QSharedDataPointer,其实就是data1)
      String addr = 0x28c798 , 0x1433f2a0 (str2的指针地址,指向一个新的QSharedDataPointer,命名为data2)
      String addr = 0x28c798 , 0x1433f2a0 (str2的指针地址,指向data2,但是修改其内容)
      String addr = 0x28c79c , 0x1433f2a0 (str1的指针地址,指向data2,不修改其内容,且放弃data1,使之引用计数为零而被彻底释放)
      String addr = 0x28c798 , 0x1433f2a0 (str2的指针地址,指向data2,不修改其内容)

      注意,str1的地址和str1.constData()地址不是一回事。

C++中的深拷贝和浅拷贝 QT中的深拷贝,浅拷贝和隐式共享的更多相关文章

  1. Qt隐式共享与显式共享

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Amnes1a/article/details/69945878Qt中的很多C++类都使用了隐式数据共 ...

  2. 关于QT中的隐式共享

    网上关于隐式共享的解释很多,在此不再陈述.本文主要是记录一下自己学习隐式共享的坑点: 即:隐式共享只发生在非指针的情况下!!!! 如下代码: QImage image1; QImage image2; ...

  3. 01Qt中的隐式共享

    隐式共享 ​ 隐式共享又称为回写复制(copy on write).当两个对象共享同一分数据时(通过浅拷贝实现数据共享),如果数据不改变,则不进行数据的复制.而当某个对象需要需要改变数据时,则进行深拷 ...

  4. C++ 语言中的重载、内联、缺省参数、隐式转换等机制展现了很多优点

    C++ 语言中的重载.内联.缺省参数.隐式转换等机制展现了很多优点,但是这些 优点的背后都隐藏着一些隐患.正如人们的饮食,少食和暴食都不可取,应当恰到好处. 我们要辨证地看待 C++的新机制,应该恰如 ...

  5. Qt隐式共享机制

    1.浅拷贝 浅拷贝-引用类型.浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同),对其中任何一个对象的改动都会影响另外一个对象. 2.深拷贝 而深拷贝-值类型.深拷贝是指源对象与 ...

  6. 可恶的QT隐式共享

    这个问题隐藏的很深,一般不容易察觉它造成的问题,而只是享受它提供的好处(节省内存,而且速度更快). 但我发现它现在至少造成两个问题: 1. 把大量的QString放到QMap里,使用完毕后清空QMap ...

  7. Qt——数据的隐式共享

    一.隐式共享类 在Qt中有很多隐式共享类( Implicitly Shared Classes ),什么是隐式共享呢,请参考官方文档的说明. 好吧,翻译一下—— 许多C++类隐式地共享数据,使得资源使 ...

  8. C++中的stack类、QT中的QStack类

    C++中的stack 实现一种先进后出的数据结构,是一个模板类. 头文件 #include<stack> 用法(以int型为例): stack <int> s; //定义一个i ...

  9. C++中的queue类、QT中的QQueue类

    C++中的queue 实现一种先进先出的数据结构,是一个模板类 头文件 #include<queue> 用法(以int型为例): queue<int> Q; //定义一个int ...

随机推荐

  1. 安装SQL Servre2000时提示“command line option syntax error! type command /? for help”

    问题: 当程序正在安装ms数据访问组件时,弹出错误提示框:command line option syntax error,type command/? for help,点击确定继续:到了程序正在安 ...

  2. javascript或node中的console用法总结

    //建立app.js页面 // 一:页面代码 console.log("log信息"); //在页面中执行(node app.js)这个文件会在控制台中看到log信息:" ...

  3. Solr 6.0 学习(五)solr基本查询和高级查询

    参考:http://www.cnblogs.com/rainbowzc/p/4354224.html 查询参数 常用: q - 查询字符串,必须的. fl - 指定返回那些字段内容,用逗号或空格分隔多 ...

  4. 你知道的,javascript语言的执行环境是"单线程模式",这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行,因此很多时候需要进行“异步模式”,请列举js异步编程的方法。

    回调函数,这是异步编程最基本的方法. 事件监听,另一种思路是采用事件驱动模式.任务的执行不取决于代码的顺序,而取决于某个事件是否发生. 发布/订阅,上一节的"事件",完全可以理解成 ...

  5. python打造XslGenerator

    0x00前言 今天加载了Demon哥分享的RSS.其中有一篇是三好学生讲的: 在仔细越读这篇文章后,我懂得了里面的一些骚操作,所以有了以下的 脚本. 0x001代码 import optparse i ...

  6. 12.solr学习速成之dataimport

    solr除了利用solrj建立索引外,还可以由列式数据库hbase触发器添加索引,自动全量或者增量索引关系数据库数据等. dataimport可以配置从任何关系数据库导入索引 1.将jar包拷贝到to ...

  7. Http中Cookie的HttpOnly和secure属性

    Cookie语法: Cookie通常是作为HTTP 应答头发送给客户端的,下面的例子展示了相应的语法(注意,HttpOnly属性对大小写不敏感):  Set-Cookie: =[; =]   [; e ...

  8. [BZOJ][CQOI2014]数三角形

    Description 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Input 输入一行,包含两个空格分隔的正整数m和 ...

  9. LR11中webservice协议的性能测试应用

    使用LR11对webservice协议的接口测试应用 脚本开发步骤:1.打开vuser generator,新建一个脚本,选择webservice协议:2.选择Manage Services(服务管理 ...

  10. 一行命令解决 xcode升级新版本插件失效问题

    sudo find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.plist -maxdepth ...