创建一个全局静态对象,类型为QGlobalStatic,名称为VariableName,行为像一个指向type的指针。 Q_GLOBAL_STATIC创建的对象在第一次使用时初始化自己,这意味着它不会增加应用程序或库的加载时间。 此外,对象是在所有平台上以线程安全的方式初始化的。用法如下,在全局上下文中(即,在任何函数体之外):  Q_GLOBAL_STATIC(MyType, staticType)。这个宏的目的是替换不是POD的全局静态对象(Plain Old Data,或者用c++ 11术语来说,不是由普通类型组成的),因此有了这个名字。 例如,c++代码创建了一个全局静态对象: static MyType staticType;与Q_GLOBAL_STATIC相比,假设MyType是一个具有构造函数、析构函数或其他非pod的类或结构体,上面的缺点如下:

1、它需要MyType的加载时初始化(也就是说,当库或应用程序加载时调用MyType的默认构造函数);

2、该类型将被初始化,即使它从未被使用;

3、不同单元之间的初始化和销毁的顺序是不确定的,导致可能在初始化之前或销毁之后使用;

4、如果它是在函数中找到的(也就是说,不是全局的),它将在第一次使用时被初始化,但许多当前的编译器(截至2013年)并不保证初始化将是线程安全的;

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

构造和析构函数:

对于Q_GLOBAL_STATIC,类型type必须是可公开默认构造和可公开销毁的。 对于Q_GLOBAL_STATIC_WITH_ARGS(),必须有一个公共构造函数来匹配传递的参数。  不能将Q_GLOBAL_STATIC用于具有受保护或私有默认构造函数或析构函数的类型(对于Q_GLOBAL_STATIC_WITH_ARGS(),一个与参数匹配的受保护或私有构造函数)。 如果有问题的类型将这些成员作为受保护的成员,则可以通过从该类型派生并创建公共构造函数和析构函数来克服这个问题。 如果该类型将它们作为private,则在派生之前必须声明友元。

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

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

如果编译器支持c++ 11继承构造函数,可以这样写: 

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

声明位置

Q_GLOBAL_STATIC宏创建的类型必须是静态的,在全局作用域中。在函数中放置Q_GLOBAL_STATIC宏是不可能的(这样做将导致编译错误)。
更重要的是,这个宏应该放在源文件中,而不是头文件中。由于结果对象是静态链接的,如果宏被放置在头文件中并包含在多个源文件中,该对象将被定义多次,不会导致链接错误。相反,每个单元将指向不同的对象,这可能导致微妙且难以跟踪。

注意,不建议将该宏用于POD类型或具有c++ 11 constexpr构造函数(一般可构造和可销毁)的类型。 对于这些类型,仍然建议使用常规的静态,无论是全局的还是函数-局部的。

这个宏可以工作,但是会增加不必要的开销。

可重入性、线程安全、死锁和异常安全 :

Q_GLOBAL_STATIC宏创建了一个对象,该对象在第一次使用时以线程安全的方式初始化:如果多个线程试图同时初始化该对象,只有一个线程将继续初始化,而其他所有线程将等待完成。

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

宏不能保证从同一个线程重入。 如果从构造函数内部直接或间接地访问全局静态对象,肯定会发生死锁。

另外,如果两个Q_GLOBAL_STATIC对象在两个不同的线程上初始化,并且每个线程的初始化序列都访问另一个,那么可能会发生死锁。 因此,建议保持全局静态构造函数简单,如果做不到,就确保在构造过程中没有交叉依赖使用全局静态函数。

销毁

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

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

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

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

这个函数是在Qt 5.1中引入的。

Q_GLOBAL_STATIC_WITH_ARGS(Type, VariableName, Arguments)

创建一个全局静态对象,类型为QGlobalStatic,名称为VariableName,由参数arguments初始化,并作为类型的指针。Q_GLOBAL_STATIC_WITH_ARGS创建的对象在第一次使用时初始化自己,这意味着它不会增加应用程序或库的加载时间。此外,对象是在所有平台上以线程安全的方式初始化的。
用法如下,在全局上下文中(即,在任何函数体之外):

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

Arguments宏形参必须始终包含括号,或者如果允许c++ 11统一初始化,则必须包含大括号。
除了使用提供的参数实际初始化内容外,这个宏的行为与Q_GLOBAL_STATIC()相同。

qt -- Q_GLOBAL_STATIC创建全局静态对象相关推荐

  1. Qt之Q_GLOBAL_STATIC创建全局静态对象

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

  2. 2020-12-14(全局/静态对象的构造函数和析构函数调用的时机以及地址)

    一般的对象实例化在什么时候实例化的呢? 是不是在main函数运行到那里的时候,然后创建对象,会调用类里面的构造函数. 那当我们遇到全局/静态对象的时候,它是不是也是需要在main函数里面慢慢构造呢? ...

  3. C++构造与析构(18) - 静态对象(static object)何时销毁

    C++的static关键字 static关键字可以用于修改局部变量,函数,类的数据成员以及对象.静态局部变量只初始化一次,然后在每次函数调用时都保持它的值.静态成员函数可以直接用类来调用,不需要创建对 ...

  4. java 静态变量 new_java中静态对象和普通变量在初始化静态变量的时候有什么区别??高手!!...

    下面有一个例子,将语句(6)直接改为一个新的对象后,结果会不同,解释的清楚一些吗??豁出去了,家当10分publicclassStaticVariableTest{privatestaticStati ...

  5. CreateMutex创建互斥内核对象

    http://blog.sina.com.cn/s/blog_149e9d2ec0102wyr0.html 在编程中我们常使用程序创建一个互斥的内核对象,目的就是为了让这个程序只能运行一次.我们都会有 ...

  6. C++之全局对象、局部对象、静态对象详解

    1. 对于全局对象,程序一开始,其构造函数就先被执行(比程序进入点更早):程序即将结束前其析构函数将被执行. 2. 对于局部对象,当对象诞生时,其构造函数被执行:当程序流程将离开该对象的声明周期时,其 ...

  7. 创建电脑对象,电脑对象有关机和开机方法(静态对象构造方法)

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...

  8. 静态对象、全局对象与程序的运行机制

    静态对象.全局对象与程序的运行机制 1.   在介绍静态对象.全局对象与程序的运行机制之间的关系之前,我们首先看一下atexit函数. atexit函数的声明为:int atexit( void ( ...

  9. 全局对象和全局静态、局部静态析构顺序

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/72904337 作者:car ...

最新文章

  1. 病案编码员需要计算机的什么知识,前辈分享:优秀编码员必须经历的成长过程,你到哪一级了?...
  2. OCM备考 一、Server config 之网络配置
  3. NET问答: 如何记录 EntityFramework 中的所有 SQL 日志 ?
  4. console java_Java Console writer()方法与示例
  5. 如果你还不了解GBDT,不妨看看这篇文章
  6. smart gesture安装失败_WinCC flexible SMART V3 SP2安装步骤以及常见错误解决方法
  7. 在微信小程序中引入 Iconfont 阿里巴巴图标库
  8. new对象后的代码块(匿名类)
  9. jquery如何阻止子元素相应mouseout事件
  10. 常见前端面试题及答案(下)
  11. AI安全 - 华为白皮书《AI Security White Paper》
  12. Java 读写txt文件
  13. 苹果笔记本macbook pro如何安装python_Mac OS系统下的安装
  14. Spring AOP具象化理解(代理模式)
  15. 解决进不去BIOS或U盘启动,windows10如何关闭快速启动
  16. TEK-DPO2024示波器使用手册
  17. 明年9月,南京大学苏州校区将正式招生!
  18. 球形FP-MAP的接收端迭代检测模型
  19. 恶意代码Lab11-03分析
  20. 自动发帖程序的一些总结

热门文章

  1. Matlab坐标系绘制
  2. nfsd linux是什么进程,如何从NFS启动Linux及原理
  3. Matlab使用-meshgrid函数(网格矩阵)
  4. 【Java虚拟机】第一章、Java虚拟机是如何产生的
  5. ios上webview与浏览器webview
  6. Python 中 concurrent.futures 模块使用说明
  7. C++ 控制台程序选择文件/文件夹
  8. IOS学习六:Date Picker, Picker View选取器控件初步
  9. 不需要密码卸载Symantec Endpoint Protection
  10. 虚拟桌面的服务器,虚拟桌面与集合