概述
在使用QString
,QByteArray
等容器时,都会碰到一个名词隐式数据共享
。说起来比较高大上,通俗一点就是写时复制(copy-on-write)
,当两个对象共享同一份数据时通过浅拷贝实现数据块的共享,如果数据不改变,不进行数据的复制。而当某个对象需要改变数据时则执行深拷贝。
例子
此处验证QString
的隐式数据共享:
1 | ... |
自行实现
需要自己实现隐式数据共享
,可以依靠Qt
提供的QSharedData
和QSharedDataPointer
。
1 | // 数据实现 |
在Test
这个类中,要注意这个数据成员d
,其为QSharedDataPointer
,所有对Test
类数据成员的访问都通过这个指针的operator->()
来操作。
对于写访问,operator->()
会自动调用detach()
,来创建一个共享数据对象的拷贝。
如果该共享数据对象的引用计数大于1的话,也可以确保向一个Test
对象执行写入操作不会影响到其他的共享同一个TestData
对象的Test
对象。
类TestData
继承自QSharedData
,它提供了幕后的引用计数。
当无论何时一个Test
对象被拷贝、复制或作为参数传值,QSharedDataPointer
都会自动增加引用计数;反之,当一个Test
对象被删除或超出作用域,引用计数会减少;当引用计数归零,该TestData
会被自动删除。
在Test
类的非const
成员函数中,无论指针何时被解引用,QSharedDataPointer
都会调用一次detach()
以保证该函数作用在一份数据拷贝上。注意,在一个成员函数中,如果对指针进行了多次解引用,而导致调用了多次detach()
,也只会在第一次调用时创建一份拷贝。
但在Test
的const
成员函数中,对指针的解引用不会导致detach()
的调用。