QT/c++相关记录
QT的大部分容器类(如 QString
、QVector
等)都是使用 隐式共享(implicit sharing) 技术,这是通过写时复制(copy-on-write, COW)实现的优化模式。理解这一点的关键在于,Qt 的容器类需要在对象拷贝时高效处理数据,而 隐式共享 则允许在栈上操作容器的同时,在需要时共享内部数据的堆上存储。以QJsonObject(其实际也可以视为一个轻量级容器)为例:
当直接在栈上创建一个QJsonObject,即QJsonObject obj;这个对象本身(包括一些元数据,如指向实际数据的指针、引用计数等)是在栈上分配的。如果对象超出了它的作用域(例如函数结束时),它在栈上被销毁。QJsonObject
的实际数据(如存储键值对的哈希表)则是在堆上分配的。这是为了支持动态分配的灵活性,尤其是当 JSON 数据量比较大或需要频繁扩展时,堆上存储更适合。多个 QJsonObject
可以共享同一个堆上的数据,直到其中某个对象尝试修改数据时,才会触发写时复制。
通过这种机制,多个 QJsonObject
可以指向同一份堆上的数据。当多个对象指向相同的数据时,它们共享这一份数据,不需要额外的内存开销。例如:
QJsonObject obj1; obj1["key"] = "value"; // 堆上分配存储空间 QJsonObject obj2 = obj1; // 只是拷贝了指针,obj2 和 obj1 共享堆上的数据
此时 obj1
和 obj2
指向同一个堆上的键值对数据。这种共享机制避免了不必要的深拷贝,提升了性能。
当需要修改数据时,Qt 采取了写时复制的策略,即当某一个对象试图写入数据(修改键值对),才会分离出该对象的专属数据副本。这时,真正的深拷贝会发生。
obj2["key"] = "new_value"; // 由于 obj2 修改了数据,它不再共享 obj1 的数据
此时,obj2
会分配新的堆内存,存储修改后的数据,而 obj1
仍然指向原始数据。
隐式共享机制的底层是引用计数,类似于智能指针,会在所有与其相关联的实例销毁时释放共享的内部数据。