Qt之Q_GLOBAL_STATIC创建全局静态对象

2023-11-20

概述

所谓的全局静态对象,大多是在单例类中所见,之前写过一篇文章介绍如何实现一个单例类,在这里,这是最常见的方式来进行创建,需要自定义 static 类对象, 并进行手动初始化。而今天要说的是更简单的方式来实现,Qt 提供了一个非常方便的宏Q_GLOBAL_STATIC,可以快速创建全局静态对象。

QGlobalStatic类

其实Q_GLOBAL_STATIC宏是在QGlobalStatic中定义的,不过通常都不会直接使用QGlobalStatic类,而是使用类中定义的宏Q_GLOBAL_STATIC,与之对应的还有一个宏Q_GLOBAL_STATIC_WITH_ARGS,后面进行介绍。

基本用法

首先我们举例看看这个宏才怎么使用:

Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
   if (globalState.exists())
       return globalState->someState;
   return QString();
}

这就创建了一个全局静态类对象staticType,MyType是类名,在上面的声明之后,staticType对象可以像使用指针一样使用,保证只能初始化一次。除了用作指针外,对象还提供了两种方法来确定全局的当前状态:exists()和isDestroyed()。

宏定义介绍

Q_GLOBAL_STATIC(Type, VariableName)

由Q_GLOBAL_STATIC创建的对象在首次使用时进行初始化,它不会增加应用程序或库的加载时间。此外,该对象在所有平台上都以线程安全的方式初始化的。
这个宏的典型用法如下,在全局上下文中(即,在任何函数体之外):

Q_GLOBAL_STATIC(MyType, staticType)

这个宏旨在替代不是POD的全局静态对象(普通的旧数据,或者用C ++ 11的术语,不是由平凡的类型组成),因此也就是名称。例如,下面的C ++代码创建一个全局静态:

static MyType staticType;

与Q_GLOBAL_STATIC相比,假设这MyType是一个具有构造函数,析构函数的类或结构,或者是非POD,上面写法有以下缺点:

  • 它需要加载时初始化MyType(即MyType加载库或应用程序时调用的默认构造函数);
  • 即使从未使用过,类型也会被初始化;
  • 不同的单元之间的初始化和破坏的顺序不确定,导致在初始化之前或销毁之后可能会使用;
  • 如果它是在一个函数内(即不是全局的)发现的,它将在第一次使用时被初始化,但是许多当前编译器中并不保证初始化是线程安全的;

Q_GLOBAL_STATIC宏通过在第一次使用时保证线程安全初始化并允许用户查询类型是否已被销毁以避免销毁后使用问题来解决上述所有问题。

注意:如果要使用该宏,那么累的构造函数和析构函数必须是公有的才行,如果构造函数和析构函数是私有或者受保护的类型,是不能使用该宏的。

对于具有受保护或私有默认构造函数或析构函数的类型(对于Q_GLOBAL_STATIC_WITH_ARGS(),一个与参数匹配的受保护或私有构造函数),不能使用Q_GLOBAL_STATIC 。如果将这些成员保护起来,可以通过从类型派生出来并创建公共构造函数和析构函数来解决问题。如果类型将它们设为私有,则派生之前需要声明friend。

例如,MyType基于先前定义的MyOtherType具有受保护的默认构造函数和/或受保护的析构函数

class MyType : public MyOtherType { };
  Q_GLOBAL_STATIC(MyType, staticType)

MyType由于析构函数是隐式成员,因此不需要定义,如果没有定义其他构造函数,则默认构造函数也是如此。但是,与Q_GLOBAL_STATIC_WITH_ARGS()一起使用时,需要一个合适的构造函数体:

 class MyType : public MyOtherType
  {
  public:
      MyType(int i) : MyOtherType(i) {}
  };
  Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42))

该宏的声明位置

Q_GLOBAL_STATIC宏在全局范围内创建一个必须是静态的类型。无法将Q_GLOBAL_STATIC宏放在函数中(这样做会导致编译错误)。

最重要的是,这个宏应该放在源文件中,千万不要放在头文件中。由于生成的对象具有静态链接,因此如果宏放置在标题中并且被多个源文件包含,该对象将被多次定义,并且不会导致链接错误。相反,每个单元将引用一个不同的对象,这可能会导致微妙且难以追踪的错误。

线程安全,死锁和构建异常安全

Q_GLOBAL_STATIC宏创建一个对象,它在首次使用时以线程安全的方式初始化自己:如果多个线程同时尝试初始化对象,则只有一个线程会继续初始化,而其他所有线程都会等待完成。

如果初始化过程抛出异常,则认为初始化未完成,并在控制达到任何对象使用时再次尝试。如果有任何线程在等待初始化,其中一个线程将被唤醒尝试初始化。

宏不能保证来自同一线程的重入。如果全局静态对象是直接或间接从构造函数中访问的,那么肯定会发生死锁。

另外,如果两个Q_GLOBAL_STATIC对象正在两个不同的线程上初始化,并且每个初始化序列都访问另一个线程,则可能会发生死锁。出于这个原因,建议保持全局静态构造器简单,否则,确保在构造过程中不使用全局静态的交叉依赖。

销毁

如果在程序生命周期中从未使用该对象,除了QGlobalStatic :: exists()和QGlobalStatic :: isDestroyed()函数外,类型Type的内容将不会创建,并且不会有任何退出时间操作。

如果该对象被创建,它将在退出时被销毁,类似于C atexit函数。在大多数系统中,事实上,如果在退出之前将库或插件从内存中卸载,也会调用析构函数。

由于销毁是在程序退出时发生的,因此不提供线程安全性。这包括插件或库卸载的情况。另外,由于析构函数不会抛出异常,因此也不会提供异常安全性。

但是,重新调用是允许的,在销毁期间,可以访问全局静态对象,并且返回的指针与销毁开始之前的指针相同。销毁完成后,不允许访问全局静态对象,除非在QGlobalStatic API中注明。

Q_GLOBAL_STATIC_WITH_ARGS(Type, VariableName, Arguments)

该宏的用法:

Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42, "Hello", "World"))

注意:宏参数需要包含在括号中。
除了使用提供的参数实际初始化内容外,该宏的行为与Q_GLOBAL_STATIC()的行为相同。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt之Q_GLOBAL_STATIC创建全局静态对象 的相关文章

  • 如何在QLineEdit/QLabel等中从左到右显示阿拉伯符号?

    在Qt的实现中阿拉伯符号显示在右到左方向 因此任何包含阿拉伯符号的字符串都将右对齐 但我的应用程序想要做的是显示所有文本左到右方向 无论是否包含阿拉伯符号 所有文本都是左对齐的 一个例子如下所示 This is 我想实现什么 就是这样QLi
  • 如何设置 QTableView 中特定单元格的线条样式?

    我正在使用 QT GUI 我正在使用 QTableView 实现一个简单的十六进制编辑控件 我最初的想法是使用一个有十七列的表格 表的每一行都有 16 个十六进制字节 然后在第十七列中显示该数据的 ASCII 表示形式 理想情况下 我想编辑
  • Qt 5.4/Qml:防止绑定循环

    我有一个全局单例 设置 它保存应用程序设置 当我尝试运行以下代码时 我得到一个QML CheckBox Binding loop detected for property checked CheckBox checked Settings
  • 除了内存管理之外,QObject 的父对象还用于什么?

    我知道 当一个QObject http doc qt io qt 5 qobject html被摧毁了 它也摧毁了它所有的孩子 但是 在我最近的所有 Qt 代码中 我总是声明任何类的成员 例如 QMainWindow https doc q
  • 选择文件夹后 QFileDialog::getExistingDirectory 不关闭

    In Qt QFileDialog dlg new QFileDialog QDir dir dlg gt getExistingDirectory this tr Choose folder qgetenv HOME 打开文件夹选择对话框
  • QMetaObject::invokeMethod 在以下情况下不起作用:

    从静态类和非主线程调用 简而言之 我有一个类 sapp 它有另一个静态类 tobj 作为静态成员 为了避免静态顺序初始化失败 tobj 在 sapp 的方法中声明 该方法又返回 tobj 实例的指针 我的问题是 tobj 有一个计时器 应该
  • App Store 上是否允许嵌入 dylib 的 iOS 8 应用程序?

    iOS 8 现在支持动态框架 是否意味着 App Store 提交允许这样做 似乎以前的开发人员能够在内部应用程序中使用 dylib 但在提交到 App Store 的内容中使用它们会导致您被拒绝 情况仍然如此 还是 iOS 8 中的这一更
  • Qt - 如何在 QGraphicsPixmapItem 中显示 gif(动画)图像

    我正在尝试在 QGraphicsPixmapItem 中使用一张闪烁的图像 显示的图像没有动画效果 下面是原始图像 下面是在 QGraphicsPixmapItem 中使用此图像的 QGraphicsScene 有人能说一下如何实现这一目标
  • 使用带有 MSVC 2015 编译器的 QT Creator 5.8

    我是新来的C 和编程 我正在尝试做一个小项目 使用Qt and Qt Creator 我当时用的是MinGW compiler 但对于这个项目 我需要与MSVC compiler 因为我需要使用QtWebEngineWidgets I ha
  • 无法锚定到不是父级或同级 QML QtQuick 的项目

    我正在使用 QML 开发 python 桌面应用程序 我的 QML 文件中有这个 SplitView anchors fill parent orientation Qt Horizontal Rectangle color 272822
  • 使用 Qt 在 xoverlay 之上绘制

    我希望在使用 Xoverlay 渲染的视频流之上绘制一些 UI 我正在使用 gstreamer 播放视频并使用 xoverlay 在 xvimagesink 上渲染它 我的小部件继承自 QGLWidget 我希望使用 QPainter 绘制
  • 在 QtCreator 中查看数组内容

    调试时是否可以在 Qt Creator 中查看数组的内容 似乎检测到我的数组是一个数组而不是一个指针 此外 我可以点击一个箭头 就像展开一样 但之后什么也没有显示 当我试穿的时候std vector Qt Creator 设法按预期显示内容
  • Qt 远程文件浏览器

    我想知道是否有人使用过 Qt 远程文件浏览器 根据我的理解 我有两个选择 当涉及到远程文件时 将 QFileDilaog 与自定义代理模型结合使用 该模型将负责提供远程文件 目录结构 使用自定义对话框 并为本地文件提供标准文件系统模型 为远
  • 删除 QComboBox“下拉”动画

    我正在使用 Qt 4 8 并且想在单击 QComboBox 时摆脱 下拉 动画 我也想稍微移动一下 到目前为止 我一直在考虑重新实现 showPopup 和 hidePopup 但不知道如何使其工作 此外 每次我尝试使用 CSS 进行移动或
  • Qt 信号槽,新符号中的转换类型[重复]

    这个问题在这里已经有答案了 鉴于以下两个 connect ui gt comboBox SIGNAL activated QString ps SLOT requestPlotsAvailable QString connect ui gt
  • Qt、PushButton、id 属性?有什么方法可以知道点击了哪个按钮

    void MainWindow addRadioToUI int button cunter 4 while database isEmpty button cunter QPushButton one new QPushButton Pl
  • 在哪里可以找到 Qt 的 dll 的 pdb 文件?

    我正在调试 Qt 应用程序 在哪里可以找到 Qt 的调试 dll 我在windows上使用的是vs2010 它说它需要 Qt 中的许多 dll 的 pdb 文件 从 Qt 5 9 开始 与 Windows 发行版相对应的 PDB 可作为单独
  • 检查目录是否为空

    我正在尝试检查目录是否为空 MainWindow MainWindow QWidget parent QMainWindow parent ui new Ui MainWindow ui gt setupUi this QDir Dir h
  • [本机]:在Qt for Android中使用Java函数和第3方库[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 最近我用qt写了一个android应用程序 但我有一个很大的问题 我可以使用 调用一些原生的android API 比如调用特殊的activit
  • Qt GUI 编程设计

    我正在尝试创建一个 GUI 应用程序 主窗口 一个QMainWindow 包含 9 个固定大小的标签以及主窗口的大小 我尝试在没有 Qt GUI Designer 的情况下以编程方式制作它 该项目构建时没有错误 但我看不到主窗口上显示的任何

随机推荐

  • ChatGPT火了,将给网络安全行业带来什么影响?

    ChatGPT是一个基于人工智能的聊天机器人 它是使用OpenAI的GPT技术构建的 能够根据用户输入的语言自动生成响应 ChatGPT可以回答各种问题 提供建议和支持 以及进行闲聊和娱乐等 它旨在为用户提供一个方便 快捷 智能的交互方式
  • 蓝桥杯-稍大的字符串

    题目 标题 稍大的串 串可以按照字典序进行比较 例如 abcd 小于 abdc 如果给定一个串 打乱组成它的字母 重新排列 可以得到许多不同的串 在这些不同的串中 有一个串刚好给定的串稍微大一些 科学地说 它是大于已知串的所有串中最小的串
  • filter函数的用法_动态数组函数系列5

    FILTER函数是筛选函数 就是在源数据中按照我们的条件筛选出我们想要的数据 除了常规的数据筛选 还可以进行多条件的 且 或者 或 的筛选 下面我们来看看这个FILTER函数怎么用 如果不想看文字 直接拉到最后看视频吧 FILTER函数语法
  • 属性,服务,事件

    属性 即设备支持的可读和 或可设置的参数功能 以一个灯为例 灯的开关就可以定义为一个属性 用户可以读取该属性的当前数值来得知灯的开关状态 也可以通过对该属性进行设置来打开或者关闭这个灯 服务 如果设备的某个功能只能设置 不能获取 那么可以将
  • 微服务系统硬件要求_全面解析微服务系统监控分层,啃透服务治理核心!

    架构师 JiaGouX 我们都是架构师 架构未来 你来不来 前言 监控 是微服务治理的一个重要环节 监控系统的完善程度直接影响到我们微服务质量的好坏 我们的微服务在线上运行时 有没有一套完善的监控体系能去了解到它的健康情况 这对整个系统的可
  • 【NPS 服务器搭建】2. 客户端完全手册

    场景 内网机器需要提供远程访问 如SSH 环境 1 一台独立ip的VPS 如阿里云服务器 2 一台内网的主机 windows linux 步骤 1 服务端中 新建客户端 2 服务端中 新建通道 2 1 点击进入通道管理 2 2 新增通道 1
  • ruoyi框架源码阅读之--redis配置

    redis配置 文章目录 redis配置 前言 一 引入依赖 二 配置信息 三 序列化文件 四 redis配置文件 五 redis工具类 六 redis接口限流 注解实现 七 redis接口限流 注解代码 总结 前言 redis的配置信息
  • Java中count++的坑

    最近做了一道题 非常容易落入陷阱 当count初始值为0 count count 和count count 运行出来的结果是不一样的 count count 运行出来的结果依旧为0 这是因为JVM运行时 会把count变量拷贝到到临时变量区
  • mongos、nanomsg、zeroMQ简述和go-mongos使用实例

    mongos nanomsg zeroMQ简述和go mongos使用实例 文章目录 mongos nanomsg zeroMQ简述和go mongos使用实例 1 mongos nanomsg简述 2 zeroMQ nanomsg和可扩展
  • dac解码芯片天梯_【关于AK4499引发的思考】选DAC,解码芯片追新有没有必要?

    春风不度玉门关 又见才子伴乐谈 标题这个问题 其实是差不多一年前有人在微博上问我的 彼时是2018年的年底 AKM宣布了其新款旗舰解码芯片AK4499诞生的消息 吸引了玩家群体不小的关注 于是便有人问我 对于准备购置或者更换解码的玩家来说
  • 老年人教程,使用N2N进行异地组网

    一 简介 1 为什么用N2N 在一般情况下 两台机器如果是处在同一个局域网下 那么这两台机器可以通过各自的内网IP进行通信 但是 在某些情况下你可能希望两个不同局域网的机器进行通信 此时 N2N 就能给我们带来一个简单快捷的解决方案 N2N
  • Applovin股价飞涨,同场竞技的汇量或将拿到相同剧本

    全球化 跨行业投资是对冲投资风险 实现超额收益的重要方式 若论什么行业在全球化投资中入门最简单 那一定是互联网 APP 游戏人人都能接触 轻松解决了对商业门槛的理解问题 所有的增长价值一清二楚 但互联网作为一个看起来非常成熟的行业 留给外界
  • visual studio:给项目添加宏定义

    插眼 参考 https blog csdn net lucky fly article details 103321220
  • 浅谈Java Enum作用与应用场景

    在实际应用中 有的变量只有几种可能取值 如人的性别只有两种可能取值 星期只有七种可能取值 在 Java语言中对这样取值比较特殊的变量可以定义为枚举类型 所谓枚举是指将变量的值一一列举出来 变量只限于列举出来的值的范围内取值 枚举是一个特殊的
  • python 列表sort函数和sorted函数应用————实现c++ sort按不同关键字排序功能

    首先基本的应用请参考其它教程 百度很多 现有列表ll 1 2 4 5 8 9 1 1 4 3 8 20 要实现排序 排序规则为 按元组第一个元素降序 如果元祖第一个元素相同按元祖第二个元祖升序 import functools def tc
  • 以太坊执行miner.start返回null( 转载)

    博文地址 http blog csdn net wo541075754 article details 78735711
  • redis之expire命令详解

    expire是设置redis过期时间的命令 需要注意的点有以下几点 expire设置过期时间的单位是秒 如设置name的过期时间为1000秒 expire name 1000 超过时间后会自动删除key 但是不一定是立即删除 因为redis
  • el-select下拉弹窗样式修改

    首先在el select上定义 popper class eloption 和 popper append to body true 使用方法如下面代码段
  • CAN总线隔离器简介

    简介 LCAN OptoAdapter是一款通用插入式电隔离适配器 完全的硬件逻辑设计 可安装在CAN网络的任何位置 快速实现CAN网络之间电隔离 独有的CAN信号调理技术 可以实现改变CAN网络拓扑结构 长支线 增加节点数目等功能 独有的
  • Qt之Q_GLOBAL_STATIC创建全局静态对象

    概述 所谓的全局静态对象 大多是在单例类中所见 之前写过一篇文章介绍如何实现一个单例类 在这里 这是最常见的方式来进行创建 需要自定义 static 类对象 并进行手动初始化 而今天要说的是更简单的方式来实现 Qt 提供了一个非常方便的宏Q