C++ 惯用法之 Nifty Counter

2023-10-30

背景

C++ 中全局对象的初始化在 main 函数执行前完成,在 main 函数执行结束前销毁。在同一源码文件中全局变量的初始化顺序和其定义顺序一致;但在不同的源码文件中其初始化顺序不一致,就有可能导致代码出错。

一般解决方法

①.概述

静态局部变量只有在第一次使用时才会初始化,并且只会初始化一次,可应用该特点解决全局变量的初始化问题。

②.构造动态对象

demoClass & getDemo
{
    static demoClass * demo = new demoClass();
    return *demo;
}

该方法中,在程序结束时 demo 指向的内存会被系统强制回收,不会造成内存泄漏,但是由于其析构函数没有被调用,就有可能造成一些必要操作没有被执行,从而引发问题。

③.构造静态对象

demoClass & getDemo
{
    static demoClass  demo 
    return demo;
}

该方法中,demo 会在其所在的源码文件中的其他全局对象销毁时一起销毁,会执行析构函数,但由于不同源码文件间全局对象销毁顺序不一致,有可能引发问题。

Nifty Counter 惯用法

①.概述

Nifty Counter 惯用法的原理就是为全局变量创建一个管理对象,通过这个管理对象进行全局变量的创建和销毁。

②.代码示例

//demoClass.h

class demoClass
{
public:
  demoClass() { std::cout << "demoClass construted " << std::endl; }
  ~demoClass() { std::cout << "demoClass deconstruted " << std::endl; }

  void func(){ std::cout << "hello world " << std::endl; }
};
//demoClassInit.h

#include "demoClass.h"

extern demoClass* demo;
class demoClassInit
{
public:
  explicit demoClassInit();
  ~demoClassInit();
  
  static int demo_Counter;
};

static demoClassInit demoInit;
//demoClassInit.cpp

#include "demoClassInit.h"

demoClass* demo = nullptr;
int demoClassInit::demo_Counter = 0;

demoClassInit::demoClassInit()
{
  if (demo_Counter++ == 0) demo = new demoClass;
}

demoClassInit::~demoClassInit()
{
  if (--demo_Counter == 0) delete demo;
}
#include "demoClassInit.h"

int main()
{
  demo->func();
    return 0;
}

在这里插入图片描述

③.原理说明

在每个需要使用全局变量的源码文件中都必须引用头文件 “demoClassInit.h”,则一定会引入一个全局静态对象 demoInit,该对象会随着本源码文件中全局变量的创建和销毁调用其构造和析构方法,从而可以对全局变量 demo 生命周期进行管理:demo 一定在第一个 demoInit 对象创建时创建,在最后一个 demoInit 对象销毁时销毁,解决了全局对象的销毁及销毁顺序问题。
在这里插入图片描述

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

C++ 惯用法之 Nifty Counter 的相关文章

  • Qt - QProcess 不工作

    我尝试启动 Internet Explorer 所以我使用下面的代码 QProcess process new QProcess this QString temp C Program Files Internet Explorer iex
  • 为什么这个 Web api 控制器不并发?

    我有一个 Web API 控制器 里面有以下方法 public string Tester Thread Sleep 2000 return OK 当我调用它 10 次 使用 Fiddler 时 我预计所有 10 次调用都会在大约 2 秒后
  • C# 方法重载决策不选择具体的泛型覆盖

    这个完整的 C 程序说明了这个问题 public abstract class Executor
  • 转换 const void*

    我有一个函数返回一个const void 我想用它的信息作为char 我可以将它投射为 C 风格的罚款 char variable但是当我尝试使用reinterpret cast like reinterpret cast
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • 传递 constexpr 对象

    我决定给予新的C 14的定义constexpr旋转并充分利用它 我决定编写一个小的编译时字符串解析器 然而 我正在努力保持我的对象constexpr将其传递给函数时 考虑以下代码 include
  • 如何将 SOLID 原则应用到现有项目中

    我对这个问题的主观性表示歉意 但我有点卡住了 我希望之前处理过这个问题的人能够提供一些指导和建议 我有 现在已经成为 一个用 C 2 0 编写的非常大的 RESTful API 项目 并且我的一些类已经变得巨大 我的主要 API 类就是一个
  • 处理右值时的 insert 与 emplace

    std string myString std unordered set
  • 在 C# 中,如何根据在 gridview 行中单击的按钮引用特定产品记录

    我有一个显示产品网格视图的页面 该表内有一列 其中有一个名为 详细信息 的超链接 我想这样做 以便如果用户单击该特定产品的详细信息单元格 将打开一个新页面 提供有关该产品的更多信息 我不确定如何确定哪个Product记录链接的详细信息以及我
  • 如何使用 Regex.Replace 从字符串中删除数字?

    我需要使用Regex Replace从字符串中删除所有数字和符号 输入示例 123 abcd33输出示例 abcd 请尝试以下操作 var output Regex Replace input d string Empty The d标识符
  • 不同 C++ 文件中的相同类名

    如果两个 C 文件具有相同名称的类的不同定义 那么当它们被编译和链接时 即使没有警告也会抛出一些东西 例如 a cc class Student public std string foo return A void foo a Stude
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • memcpy/memmove 到联合成员,这是否设置“活动”成员?

    重要说明 一些评论者似乎认为我是从工会抄袭的 仔细看memcpy 它从普通旧地址复制uint32 t 它不包含在联合中 另外 我正在复制 通过memcpy 到工会的特定成员 u a16 or u x in a union 不直接到整个联盟本
  • 如何在 C# 中创建异步方法?

    我读过的每一篇博客文章都会告诉您如何在 C 中使用异步方法 但由于某些奇怪的原因 从未解释如何构建您自己的异步方法来使用 所以我现在有这段代码使用我的方法 private async void button1 Click object se
  • 模板类的模板构造函数的 C++ 显式模板特化

    我有一个像这样的课程 template
  • C++ 对象用 new 创建,用 free() 销毁;这有多糟糕?

    我正在修改一个相对较大的 C 程序 不幸的是 并不总是清楚我之前的人使用的是 C 还是 C 语法 这是在一所大学的电气工程系 我们 EE 总是想用 C 来做所有事情 不幸的是 在这种情况下 人们实际上可以逃脱惩罚 但是 如果有人创建一个对象
  • 模板类中的无效数据类型生成编译时错误?

    我正在使用 C 创建一个字符串类 我希望该类仅接受数据类型 char 和 wchar t 并且我希望编译器在编译时使用 error 捕获任何无效数据类型 我不喜欢使用assert 我怎样才能做到这一点 您可以使用静态断言 促进提供一个 ht
  • Visual Studio 2015:v120 与 v140?

    仅供参考 Win10 x64 我今天开始尝试 Visual Studio 2015 在弄清楚如何运行 C C 部分后 我尝试加载一个大型个人项目 该项目使用非官方的glsdk http glsdk sourceforge net docs
  • 代码中的.net Access Forms身份验证“超时”值

    我正在向我的应用程序添加注销过期警报 并希望从我的代码访问我的 web config 表单身份验证 超时 值 我有什么办法可以做到这一点吗 我认为您可以从 FormsAuthentication 静态类方法中读取它 这比直接读取 web c
  • EntityFramework 6.0.0.0 读取数据,但不插入

    我创建了一个基于服务的数据库 folderName gt Add New Item gt Data gt Service based Database文件到 WPF 应用程序中 然后我用过Database First方法并创建了Person

随机推荐

  • k8s 证书生成 cfssl

    命令下载工具 傻瓜式执行 wget https pkg cfssl org R1 2 cfssl linux amd64 wget https pkg cfssl org R1 2 cfssljson linux amd64 wget ht
  • Verdi实现信号的平移

    在Verilog System verilog中 xxx可以实现延迟指定时间的功能 而在使用verdi查看信号波形并进行分析时 同样也可以实现类似的功能 注 这种信号平移是有其应用场景的 例如 在某些仿真模型中 为了模拟实际的信号延迟 信号
  • 极光笔记

    随着全球化进程的深入 跨境数据传输与存储问题已经变得愈发重要 推送服务的数据中心节点选择不仅关乎数据访问速度和用户体验 同时也直接牵扯到数据合规性和安全保障 EngageLab Push深知这一点 为了满足更多国际客户和全球用户触达需求 我
  • java resultset获取列数_Java语言如何获取ResultSet的行数和列数

    ResultSet接口表示在数据库的数据表中查询的结果集 ResultSet 对象具有指向其当前数据行的指针 最初 指针被置于第一行之前 Java没有提供直接返回ResultSet行数的函数 或方法 如果想知道ResultSet的行数 有以
  • 图像去噪的快速入门学习

    1 理论基础 数学基础 高等数学 线性代数 概率统计 矩阵论 数值分析等 信号处理 统计信号处理 统计学习理论等 2 文献资料阅读 常用的数据库 IEEE IEE Electronic Library Elsevier SpringerLi
  • Python(4) Numpy,控制台完全输出ndarray

    import numpy as np np set printoptions threshold np nan print ndarray 当ndarray里面的存放的数据维度过大时 在控制台会出现不能将ndarray完全输出的情况 中间部
  • NDIS网络数据监控程序NDISMonitor(3)-----NdisMonitro应用程序(C#)

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家拍砖 1 主窗口Load函数ctrlForm Load 1 先调用GetExtensions来获得运行目录下bin目录中的所有文件 通过载入为A
  • 【maven】The forked VM terminated without saying properly

    1 概述 转载 https blog csdn net zhglance article details 53695653 一直在使用Maven开发项目 最近遇到了一个让人头疼的问题 在网上搜索竟然没有找到中文描述的解决方式 自己找了英文网
  • linux内核中GPIO的使用(一)--IO内存

    一 相关概念 使用IO内存将物理地址映射为虚拟地址 再通过对虚拟地址的操作来控制硬件 所谓的IO内存是指一种编址方式 不同cpu平台使用的编址方式不同 一种是 IO内存 方式 也叫统一编址方式 是指内存和外设的地址是在同一个地址空间上的 如
  • 手把手教你使用Segformer训练自己的数据

    使用Segformer训练自己的数据 系统配置 代码链接 针对MMCV 选择系统 Windows环境要求 ubuntu 18 04 安装swin segmentation 制作VOC 数据集 代码部分修改 开始训练 使用Transforme
  • mysql实时监控工具mytop

    mysql实时监控工具mytop mytop类似于linux top工具 可以实时监控mysql服务器的性能信息 安装依赖 yum install y perl CPAN cpan cpan gt install DBI cpan gt i
  • vmwaeESXi导出虚拟机和安装

    找到你要导出的虚拟机点击 操作 选择导出 点击 导出 导出的文件会通过浏览器下载到本地 点击创建 注册 选择 从OVF或OVA文件部署虚拟机 点下一页 输入 虚拟机名称 然后点击 单机以选择文件或拖放 以下三个文件就是导出的虚拟机 将三个文
  • docker学习:实战commit

    这里的commit是把你修改后的一个容器打包成一个镜像 这样你本地就多了一个image镜像 有什么用呢 就是你在之前的镜像上的修改连同镜像 成为一个新的image 下次你去布置启动这个修改后的镜像就不用 先下载一个镜像再修改 直接拿你这次c
  • 正则表达式作业

    利用正则表达式完成下面的操作 一 不定项选择题 能够完全匹配字符串 010 62661617 和字符串 01062661617 的正则表达式包括 ABD A r d 3 d 8 B r 0 9 C r 0 9 d D r d d 能够完全匹
  • day049:异常、throws声明异常、throw抛出异常、异常的处理方式

    接下节 day050 try catch 常见问题 throwable的成员方法 自定义异常 ZQyyds 的博客 CSDN博客 一 异常 1 什么是异常 指程序出现了不正常的情况 程序在执行过程中 出现的非正常情况 最终会导致JVM的非正
  • Java课题笔记~JSON

    3 1 概述 概念 JavaScript Object Notation JavaScript 对象表示法 如下是 JavaScript 对象的定义格式 name zhangsan age 23 city 北京 接下来我们再看看 JSON
  • 整理:学术论文发表过程中的审稿人意见答复技巧

    整理 学术论文发表过程中的审稿人意见答复技巧 更新历史 20200613 首次发布 科技论文投稿后 通常都需要答复审稿人的意见 对于审稿人的意见 不能随便敷衍 因为这会让审稿人感到不高兴 说不定转头就把论文拒了 因此 需要按照合适的方式或者
  • rsync linux间同步文件及文件夹

    有时候本地写代码想同步到另一台电脑 又不想push上git 用linux自带的rsync 工具 方便快捷 将本地的salmon目录同步到ray ubuntu电脑上 rsync av salmon ray ray ubuntu home ra
  • 关于服务器环境搭建

    前言 在很多新项目中 都会用到环境搭建的情况 今天教大家如何在服务器中部署应用的环境搭建 一 搭建环境是什么 搭建环境是指建立运行程序文件的基础环境 比如服务运行需要装什么软件都需要哪些程序 服务器的部署就是搭建环境 整理了很久 刚开始搭建
  • C++ 惯用法之 Nifty Counter

    背景 C 中全局对象的初始化在 main 函数执行前完成 在 main 函数执行结束前销毁 在同一源码文件中全局变量的初始化顺序和其定义顺序一致 但在不同的源码文件中其初始化顺序不一致 就有可能导致代码出错 一般解决方法 概述 静态局部变量