Qt中的很多C++类通过使用隐式数据共享来最大化资源的使用效率和最小化复制的资源耗费。将隐
式共享类作为参数传递不仅安全而且效率高,因为在这个过程中只有指向这个数据的指针被传递,
并且当且仅当有函数对这个数据进行写操作时,才会对该数据进行复制。
一个共享类包括一个指向一个共享数据块的指针,共享数据块由数据和对共享数据进行引用的数目。
当一个共享对象被创建时,共享数据的引用数目会被设置为1.无论何时,只要有一个新的对象引用该
共享数据,该共享数据对应的这个引用数目都会加一,相反,若有对象不再引用该共享数据时,其对
应的引用数目将会减一。当共享数据的引用数目为0时,该共享数据就会被撤销掉。
当处理共享对象时,有两种方法来复制一个对象。我们常常将其称为深拷贝和浅拷贝。深拷贝会隐式的
复制一个对象。而钱拷贝只是引用的复制,即只是一个指向共享数据块的指针的复制。做一次深拷贝
会占用很大的内存和CPU资源。然而,做一次浅拷贝则很快,因为那仅仅需要处理指针的设置和引用数目
的增加。
隐式共享对象的赋值是通过浅拷贝来实现的
共享的好处是程序不需要对数据进行不必要的复制,这样就降低了内存的使用并且减少了数据的复制。
对象可以容易地被复制,作为函数的参数传递,作为函数的返回值。
隐式共享发生在场景背后,程序员不必担心它。甚至在多线程应用程序中,隐式共享也会像在多线程和隐式共享类中描述
的那样发生。
但要实现你自己的隐式共享类时,可以使用QSharedData和QSharedDataPointer这两个类。
隐式共享的细节
如果对象即将改变或引用数目大于一时,隐式共享会自动从共享的块上脱离着个对象。(这通常被称为写时拷贝或值语义)一个隐式共享类有他内部数据的总控制。在任何成员函数中修改它的数据,它将在数据修改之前,自动脱离共享数据块。
下面的类列表中,如果他们的对象将要改变时,对象将会从共享数据脱离。程序员甚至没注意到对象是共享数据的。那样你应该
把他们单独的实例当作单独的对象。他们总是表现的像单独的对象一样,但是只要有可能就依然存在添加的数据共享的好处。这
样,你可以通过值将这些类的实例作为参数传递给函数,而不必关心复制的总开销。
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 自动脱离共享数据。
paint.drawText(0,50, "Hi");
paint.end();
在这个例子中,p1 和 p2 共享数据,直到为p2调用函数QPainter::begin() ,因为画一副图将会改变这幅图。