Qt扫盲--隐式共享基本原理

隐式共享基本原理

  • 一、快速了解
  • 二、详细情况

一、快速了解

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

这篇文章主要是说,隐式共享的大概意思。
关于容器、线程中的隐式共享,以及自定义实现隐式共享,大概不谈及。

隐式数据共享是在我们底层一些的,但是我们还是应该将它们的单独实例视为单独的对象。 它们将始终作为单独的对象,但具有尽可能共享数据的额外好处。因此,我们还是可以通过值将这些类的实例作为参数传递给函数,而不用担心复制开销。

QPixmap p1, p2;
p1.load("image.bmp");
p2 = p1;                        // p1 and p2 共享相同资源

QPainter paint;
paint.begin(&p2);               // 用的p2的值,其实在底层用的是p1对象的值
paint.drawText(0,50, "Hi");
paint.end();

p2.caled(200, 200);				//p2发生修改时拷贝,此时的 p1 p2底层是两个对象

二、详细情况

一个共享类含有指向共享数据块的指针组成;数据块里有两个部分【重点关注的是数据块里的东西】

  • 引用计数
  • 共享数据

计数器的功能:创建共享对象时,它会将引用计数设置为1。每当新对象引用共享数据时,引用计数就会增加,而当对象取消引用共享数据时,引用计数就会减少。当引用计数变为零时,共享数据将被删除。

在传递函数参数、或者处理共享对象时,有两种复制对象的方法。我们通常谈论深浅拷贝。深拷贝意味着复制一个对象。浅拷贝是一个参考副本,即在只读操作时只是传递一个指向共享数据块的指针。就内存和CPU而言,深拷贝可能代价较大。但浅拷贝非常快,因为它只需要设置指针和增加引用计数就行。

  • 隐式共享对象的对象分配(运算符=())是使用浅拷贝实现的。

共享的好处: 在程序中不需要进行不必要的复制数据,从而减少内存使用和数据复制操作运算。对象可以很容易地分配、作为函数参数发送和从函数返回。隐性分享大多发生在幕后;我们其实很少需要担心它。

更改对象值时共享的内部机制: 如果对象即将更改并且引用计数大于1时,隐式共享会自动将对象从共享块中分离。这通常被称为写时复制。隐式共享的类可以控制它的内部数据。在任何修改其数据的成员函数中,它会在修改数据之前自动分离。

就像Qt中的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
      }
  }

你可能感兴趣的:(#,▶,Qt扫盲,qt,开发语言,c++,隐式共享,qt隐式内存共享)