首页 > 其他分享 >Qt 隐式共享

Qt 隐式共享

时间:2023-08-05 22:25:28浏览次数:41  
标签:p2 Qt 对象 复制 共享 数据 隐式

Qt中的许多c++类使用隐式数据共享来最大化资源使用并最小化复制。隐式共享类作为参数传递时既安全又高效,因为只传递指向数据的指针,并且只有当函数写入数据时才会复制数据,即写时复制。

 

概述

共享类由指向包含引用计数和数据的共享数据块的指针组成。

 

当创建共享对象时,它将引用计数设置为1。每当新对象引用共享数据时,引用计数递增,当对象取消引用共享数据时,引用计数递减。当引用计数变为零时,将删除共享数据。

 

在处理共享对象时,有两种复制对象的方法。我们通常讲深拷贝和浅拷贝。深度拷贝意味着复制一个对象。浅拷贝是一种引用拷贝,即只是一个指向共享数据块的指针。就内存和CPU而言,进行深度复制可能代价高昂。创建浅拷贝非常快,因为它只需要设置一个指针并增加引用计数。

 

隐式共享对象的对象赋值(带operator=())是使用浅拷贝实现的。

 

共享的好处是程序不需要不必要地复制数据,从而减少内存使用和数据复制。对象可以很容易地分配,作为函数参数发送,并从函数返回。

 

隐性分享大多发生在幕后;程序员很少需要担心这个问题。然而,Qt的容器迭代器与STL中的容器迭代器具有不同的行为。阅读隐式共享迭代器问题

 

在多线程应用程序中,隐式共享发生,如线程和隐式共享类中所述。

 

在实现自己的隐式共享类时,请使用QSharedData和QSharedDataPointer类。

 

细节

如果对象即将更改且引用计数大于1,隐式共享会自动将对象从共享块中分离出来。(这通常被称为写时复制或值语义。)

 

隐式共享类控制其内部数据。在任何修改其数据的成员函数中,它在修改数据之前自动分离。但是,请注意容器迭代器的特殊情况;参见隐式共享迭代器问题。

 

QPen类使用隐式共享,从所有更改内部数据的成员函数中分离共享数据。

代码段:

void QPen::setStyle(Qt::PenStyle style)
{
    detach();           // detach from common data 与公共数据分离
    d->style = style;   // set the style member 设置样式成员
}

void QPen::detach()
{
    if (d->ref != 1) {
        ...             // perform a deep copy 执行深度复制
    }
}

 

 

类列表

如果要更改对象,下面列出的类将自动与公共数据分离。程序员甚至不会注意到对象是共享的。因此,您应该将它们的单独实例视为单独的对象。它们将始终作为单独的对象,但在任何可能的情况下都具有共享数据的额外好处。出于这个原因,您可以将这些类的实例作为参数按值传递给函数,而不必担心复制开销。

 

QPixmap p1, p2;
p1.load("image.bmp");
p2 = p1;                        // p1 and p2 share data P1和p2共享数据【浅拷贝】

QPainter paint;
paint.begin(&p2);               // cuts p2 loose from p1 将p2从p1中分离出来【深拷贝】
paint.drawText(0,50, "Hi");
paint.end();

在这个例子中,p1和p2共享数据,直到对p2调用QPainter::begin(),因为绘制像素图会修改它。

 

警告】:在使用stl风格的迭代器时,要小心复制隐式共享容器(QMap、QVector等)。参见隐式共享迭代器问题

 

隐式共享类列表

 

标签:p2,Qt,对象,复制,共享,数据,隐式
From: https://www.cnblogs.com/tingtaishou/p/17608740.html

相关文章

  • 最简单的Qt连接MYSQL的方法
    最简单的Qt连接MYSQL的方法⭐当我试图在项目中连接本地的mysql时,反复出现:QMYSQLdrivernotloaded,显示没有成功加载mysql的驱动,在网上查询了很多教程和视频,大多为互相转载且老旧,耗费了大半天还是没有构建成功,通常的解决方法是在本地构建mysql驱动(通过安装qt时勾选的src选项里......
  • Qt5Agg TxAgg和WXAgg的区别
    https://www.oschina.net/question/12_3252 AGG,全名:Anti-GrainGeometry,是一个开源的、高效的2D图形库。AGG的功能与GDI+的功能非常类似,但提供了比GDI+更灵活的编程接口,其产生的图形的质量也非常高,而且它是跨平台的,其宣传可以在非常多的操作系统上运行。主要的功能有:1、支......
  • QT(4)信号、SLOT和QMap - Addressbook例子2
    在之前的MeeGo开发者(五):QT(3)对象和继承小例子基础上,我们增加三个button,参考http://doc.qt.nokia.com/latest/tutorials-addressbook-part2.html、http://doc.qt.nokia.com/latest/tutorials-addressbook-part3.html和http://doc.qt.nokia.com/latest/tutorials-addressbook-part......
  • 初识QT、窗口以及信号槽
    1基本规范:无论是写什么样的代码,第一步都应该是创建一个程序对象#include<QApplication>intmain(intargc,char*argv[]){QApplicationa(argc,argv);//创建对象并调用构造函数returna.exec();//因为是gui界面开发,那么程序的生存周期应该是一直存在的}2d......
  • 剖析Disruptor:为什么会这么快?(三)伪共享(转)
    缓存系统中是以缓存行(cacheline)为单位存储的。缓存行是2的整数幂个连续字节,一般为32-256个字节。最常见的缓存行大小是64个字节。当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。缓存行上的写竞争是运行在SMP系统中并行线程实现......
  • 为什么程序计数器、虚拟机栈和本地方法栈是线程私有的呢?为什么堆和方法区是线程共享的
    程序计数器、虚拟机栈和本地方法栈是线程私有的,而堆和方法区是线程共享的,这是由于它们在Java虚拟机中的作用和特性所决定的。程序计数器:程序计数器是一块较小的内存区域,用于存储当前线程正在执行的字节码指令的地址。每个线程都有自己独立的程序计数器,用于记录各自线程的执行......
  • 十五、基于MQTT协议上传属性至ONENET Studio
    1.准备工作(1)下载MQTT透传固件(安心可官网下载即可)(2)下载MQTT固件到ESP82662.AT指令连接设备上传属性值(1)AT\r\n(2)AT+RST\r\n(3)AT+CWMODE=1\r\n(4)AT+CWDHCP=1,1\r\n(5)AT+CWJAP="WIFISSID","密码"\r\n//连接路由器(6)AT+MQTTUSERCFG=0,1,"设备名/设备id","产品I......
  • Qt 在线程中invokeMethod采用QueuedConnection模式,调用带指针参数槽,实际不会调用
    widgetObject有操函数Test:voidTest(int*v);在线程中调用Test,会被忽略,实际不会调用。QMetaObject::invokeMethod(widgetObject,"Test",Qt::QueuedConnection,Q_ARG(int*,&v));下面是网上找的理由: 在同一个线程中当信号和槽都在同一个线程中时,值传递参数和引用传递参数有......
  • Qt 通过ADS实现倍福TwinCAT通信
    ADS通信分为两种:同步方式和异步方式。同步方式ADS客户端向ADS服务器发送ADS请求,在通信过程中客户端程序停止执行,直到获得ADS服务器返回的响应又可分为变量名方式和地址方式异步方式ADS客户端向ADS服务器发送ADS请求,同时客户端继续自己的工作。ADS服务器处理......
  • Qt 调用倍福TwinCAT通讯模块(TcAdsDll)
    Qt实现TwinCAT通讯目前这种方式是通过调用TwinCAT提供的AdsApi与倍福PLC通讯的。要求本机安装TwinCAT(无需作为主机,但是可能这个api依赖TwinCAT的一些服务)。关于AdsApi的官方资料请看这里,有函数的详细解释,还有例子。你值得拥有。https://infosys.beckhoff.com/english.php?conte......