当前位置: 首页 > web >正文

项目优化中对象的隐式共享

目录

一、项目优化背景       

二、继承QSharedData方式

2.1 继承QSharedData 定义数据

 2.2 QSharedDataPointer管理数据

2.3 测试使用

三、QSharedData原理

四、总结

          


一、项目优化背景
       

         在Qt框架中QString字符串 QByteArray字节数组 QImage图像类型 QList QVector Qmap等容器类 QVariant通用容器值 QPen QBrush等绘图相关类都是隐式共享的,即读时共享写时复制,极大的提高了对象的拷贝和存储效率,对于大对象的拷贝等很友好;但是项目中难免有一些自定义的大对象,如果能够享受这种隐式共享的福利也能提升软件的效率。

二、继承QSharedData方式

        在Qt框架中可以很方便的让自定义数据继承QSharedData类,进而使用QSharedDataPointer管理数据即可使得数据拥有隐式共享的能力,以下是继承QSharedData的代码举例说明:

2.1 继承QSharedData 定义数据


#include <QSharedData>
class PersonData : public QSharedData {
public:QString name;int age;PersonData() : age(0) {}PersonData(const QString &n, int a) : name(n), age(a) {}
};

 2.2 QSharedDataPointer管理数据


#include <QSharedDataPointer>
class Person {
private:// 使用隐式共享指针 引用计数管理生命周期 读时共享写时复制QSharedDataPointer<PersonData> d;public:Person() : d(new PersonData) {}Person(const QString &name, int age) : d(new PersonData(name, age)) {}// 拷贝构造函数是隐式的,浅拷贝Person(const Person &other) : d(other.d) {}// 赋值运算符也是浅拷贝Person &operator=(const Person &other) {d = other.d;return *this;}~Person() {}// 修改数据时自动触发深拷贝(写时复制)void setName(const QString &name) {d.detach(); // 如果当前有多个引用者,则复制一份新的数据并d指向该新数据d->name = name;}void setAge(int age) {d.detach(); // 如果当前有多个引用者,则复制一份新的数据d->age = age;}QString name() const { return d->name; }int age() const { return d->age; }
};

2.3 测试使用

void TestQSharedData()
{Person p1("Alice", 25);Person p2 = p1; // 浅拷贝,共享同一个PersonDataqDebug() << "p1:" << p1.name() << p1.age(); // 输出: Alice 25qDebug() << "p2:" << p2.name() << p2.age(); // 输出: Alice 25// 修改p2的数据,此时触发detach()p2.setAge(30);qDebug() << "p1 after p2 modification:" << p1.name() << p1.age(); // 输出: Alice 25qDebug() << "p2 after modification:" << p2.name() << p2.age();     // 输出: Alice 30
}

三、QSharedData原理


        隐式共享指针基本原理和共享指针一样,都是基于引用计数判定是否进行实际对象的删除,类似于shared_ptr;只是在此基础上对于对象的修改做了优化,detach操作判定引用计数为大于1时会重新创建对象,即写时复制。
        区别于std::shared_ptr若需要两个指针独立时必须进行深拷贝如下:
std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::shared_ptr<int> p2 = std::make_shared<int>(*p1);  // 拷贝 p1 指向的值

SharedPointer只需要在修改前detach即可。

基于引用计数的隐式共享实现原理(简化):

基于引用计数的隐式共享实现原理(简化)
template <typename T>
class SharedPointer {
public:SharedPointer() : data(nullptr), refCount(new int(1)) {}SharedPointer(const SharedPointer& other): data(other.data), refCount(other.refCount) {++(*refCount);}SharedPointer& operator=(const SharedPointer& other) {if (this != &other) {if (--(*refCount) == 0) {delete data;delete refCount;}data = other.data;refCount = other.refCount;++(*refCount);}return *this;}~SharedPointer() {if (--(*refCount) == 0) {delete data;delete refCount;}}T* operator->() { return data; }//前面与共享指针类似 detach基于refcnt进行深拷贝void detach() {if (*refCount > 1) {T* newData = new T(*data);--(*refCount);data = newData;refCount = new int(1);}}
private:T* data;int* refCount;
};

四、总结

        Qt的隐式共享和享元模式提供了以下优势:

内存效率:减少不必要的数据复制

性能优化:值传递变得轻量级

简洁API:无需手动管理引用计数

灵活性:结合const引用可进一步优化性能在实际开发中,应当:优先通过const引用传递隐式共享对象需要修改时使用非const引用返回值时直接返回对象(不要返回指针)注意线程安全限制 



    
  
    
 

http://www.xdnf.cn/news/16697.html

相关文章:

  • 从单机架构到分布式:Redis为何成为架构升级的关键一环?
  • 【开源项目】轻量加速利器 HubProxy 自建 Docker、GitHub 下载加速服务
  • Less Less基础
  • Docker学习相关视频笔记(二)
  • 负载均衡、算法/策略
  • ROUGE-WE:词向量化革新的文本生成评估框架
  • Java 9 新特性解析
  • 考古学家 - 华为OD统一考试(JavaScript 题解)
  • 算法第29天|动态规划dp2:不同路径、不同路径Ⅱ、整数拆分、不同的二叉搜索树
  • uipath数据写入excel的坑
  • Python 程序设计讲义(25):循环结构——嵌套循环
  • 《Spring Cloud Gateway 深度剖析:从核心原理到企业级实战》
  • WAIC 2025观察:昇腾助力AI融入多元化生活场景
  • 理解Transformer解码器
  • Github 连接救星,完全合规合法,无风险!
  • 操作系统-lecture2(操作系统结构)
  • 微服务 01
  • Objective-c 初阶——异常处理(try-catch)
  • Typecho handsome新增评论区QQ,抖音,b站等表情包
  • 用FunASR轻松实现音频转SRT字幕:完整脚本与解析
  • iOS仿写 —— 计算器
  • Python 程序设计讲义(28):字符串的用法——格式化字符串
  • [leetcode] 组合总和
  • 冒泡排序算法
  • Java中什么是类加载?类加载的过程?
  • bash变量名不能有连字符
  • 【Redis实现基础的分布式锁及Lua脚本说明】
  • 爬虫逆向之瑞数五案例:某某医学院(补环境,联调)
  • Makefile 快速入门指南
  • 嵌入式第十四课!!!指针在字符数组的应用与数组指针