JsonCPP源码分析——分配器和配置器

1、allocator.h文件
该文件定义了一个分配器模版,该文件主要使用了内存对齐控制、rebind机制(C++ 标准库的分配器接口要求提供 rebind 机制,以支持不同类型的分配)、::operator new、std::addressof等技术。

  • 内存对齐控制:之所以先保存当前内存对齐方式,最后再恢复,是想把json对象的内存对齐方式和使用它的对象的内存方式隔离开
#pragma pack(push)  //保存当前内存对齐方式
#pragma pack() // 使用编译器默认内存对齐方式... // 使用默认内存对齐方式的代码
#pragma pack(pop) // 恢复之前的内存对齐方式
  • rebind机制: C++ 标准库的分配器接口要求提供 rebind 机制,以支持不同类型的分配,rebind 机制可以理解为允许分配器为不同类型的对象分配内存空间。这种机制使得标准库容器能够使用相同的分配器实例来分配其所有元素类型的内存。rebind 机制允许你通过一个分配器类型生成另一个类型的分配器。例如,如果你有一个 SecureAllocator,你可以通过 rebind 机制得到一个SecureAllocator,从而使用相同的分配器为 double 类型的对象分配内存。使用方式如下:
SecureAllocator<int> intAlloc;
SecureAllocator<int>::rebind<double>::other doubleAlloc;
  • ::operator new: 只分配空间而不调用构造函数,如果直接new,既分配空间又调用构造函数。前者需要程序员控制调用构造函数,析构函数,销毁空间,后者直接delete或delete []即可。
  • std::addressof是C++11新引入的,它的主要作用是获取对象的地址,这样的优点是放在类对&进行重写而改变了取地址的含义。
#ifndef JSON_ALLOCATOR_H_INCLUDED
#define JSON_ALLOCATOR_H_INCLUDED#include <cstring>
#include <memory>
/*
预处理命令#pragma pack(push)用来保存当前的内存对齐方式
#pragma pack()用来使用编译器默认的内存对齐方式
*/
#pragma pack(push)
#pragma pack()namespace Json {
template <typename T> class SecureAllocator {
public:// 类型定义using value_type = T;using pointer = T*;using const_pointer = const T*;using reference = T&;using const_reference = const T&;using size_type = std::size_t;using difference_type = std::ptrdiff_t;// 默认构造函数SecureAllocator() {}// 拷贝构造函数模板template <typename U> SecureAllocator(const SecureAllocator<U>&) {}// rebind 结构体模板template <typename U> struct rebind { using other = SecureAllocator<U>; };// 分配内存pointer allocate(size_type n) {return static_cast<pointer>(::operator new(n * sizeof(T)));}// 释放内存void deallocate(pointer p, size_type n) {memset_s(p, n * sizeof(T), 0, n * sizeof(T));::operator delete(p);}// 在已分配内存上构造对象,就地构造template <typename... Args> void construct(pointer p, Args&&... args) {::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);}// 获取对象的地址pointer address(reference x) const { return std::addressof(x); }const_pointer address(const_reference x) const { return std::addressof(x); }// 获取最大可分配数量size_type max_size() const { return size_t(-1) / sizeof(T); }// 在已分配内存上销毁对象void destroy(pointer p) {p->~T();}
};// 比较操作符
template <typename T, typename U>
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {return true;
}template <typename T, typename U>
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {return false;
}
} // namespace Json//恢复原有的内存对齐方式
#pragma pack(pop)#endif // JSON_ALLOCATOR_H_INCLUDED

2、config.h文件

  • 动态库导入导出符号在不同的平台和编译器中的处理方式不一样,需要对导出的符号进行特定的处理,以确保正确导出和导入。JSON_DLL_BUILD:在编译动态库时定义。用于标识正在编译动态库。JSON_DLL:在使用动态库时定义。用于标识正在使用动态库。JSON_API:根据不同的编译器和平台,定义导出和导入符号的宏。可以理解为在编译动态库和使用动态库时,JSON_API的值是不一样的。
// Export macros for DLL visibility
#if defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#elif defined(__GNUC__) || defined(__clang__)
#define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER)#elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#endif // ifdef JSON_DLL_BUILD#if !defined(JSON_API)
#define JSON_API
#endif
  • MSVC版本兼容性
#if defined(_MSC_VER) && _MSC_VER < 1800
#error                                                                         \"ERROR:  Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
#endif#if defined(_MSC_VER) && _MSC_VER < 1900
// As recommended at
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,const char* format, ...);
#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
#else
#define jsoncpp_snprintf std::snprintf
#endif
  • 根据编译器版本设置弃用宏JSONCPP_DEPRECATED,它可以向编译器表明某个函数或变量已被弃用,并提供一个弃用消息。
#ifdef __clang__
#if __has_extension(attribute_deprecated_with_message)
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#endif
#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
#endif                  // GNUC version
#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates// MSVC)
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif // __clang__ || __GNUC__ || _MSC_VER#if !defined(JSONCPP_DEPRECATED)
#define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif
  • 类型定义,std::conditional:根据条件选择不同的类型,std::basic_string:使用自定义分配器的字符串类型,std::basic_istringstream 和 std::basic_ostringstream:使用自定义分配器的字符串输入输出流
namespace Json {
using Int = int;
using UInt = unsigned int;
#if defined(JSON_NO_INT64)
using LargestInt = int;
using LargestUInt = unsigned int;
#undef JSON_HAS_INT64
#else
#if defined(_MSC_VER)
using Int64 = __int64;
using UInt64 = unsigned __int64;
#else
using Int64 = int64_t;
using UInt64 = uint64_t;
#endif
using LargestInt = Int64;
using LargestUInt = UInt64;
#define JSON_HAS_INT64
#endiftemplate <typename T>
// JSONCPP_USING_SECURE_MEMORY 为true,使用SecureAllocator<T>, 为false,使用std::allocator<T>
using Allocator = typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>, std::allocator<T>>::type;
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
using IStringStream = std::basic_istringstream<String::value_type, String::traits_type, String::allocator_type>;
using OStringStream = std::basic_ostringstream<String::value_type, String::traits_type, String::allocator_type>;
using IStream = std::istream;
using OStream = std::ostream;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/45690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C++ 入门:第一个小程序》

《C 入门&#xff1a;第一个小程序》 在学习 C 的旅程中&#xff0c;编写第一个小程序是一个令人兴奋的时刻。它就像打开一扇通往新编程世界的大门&#xff0c;让我们初步领略 C 的魅力。 C 是一种强大而灵活的编程语言&#xff0c;广泛应用于各种领域&#xff0c;从系统编程…

python 方向梯度直方图(HOG)算法 【附两种实现方法并可视化】

目录 一、概述1.1 算法定义1.2 实现过程二、方法1(skimage库)2.1 代码实现2.2 结果示例三、方法2(cv2库)3.1 代码实现3.2 结果示例四、结果对比🙋 结果预览 一、概述 1.1 算法定义 方向梯度直方图(Histogram of Oriented Gradient,HOG):是应用在计算机视觉和图像处…

Telegram Bot、小程序开发(三)Mini Apps小程序

文章目录 一、Telegram Mini Apps小程序二、小程序启动方式三、小程序开发小程序调试模式初始化小程序Keyboard Button Mini Apps 键盘按钮小程序【依赖具体用户信息场景,推荐】**Inline Button Mini Apps内联按钮小程序**initData 的自动传递使用内联菜单时候哪些参数会默认传…

LLM微调

文章目录 一. 常见微调分类1.1 全量微调&#xff08;FFT&#xff1a;Full Fine-tuning&#xff09;1.2 参数高效微调(PEFT&#xff1a;Parameter-Efficient Fine-Tuning)1.3 指令微调&#xff08;IFT&#xff1a;Instructional Fine-tuning&#xff09;1.3.1 Hard prompt1.3.2 …

Docker存储目录问题,如何修改Docker默认存储位置?(Docker存储路径、Docker存储空间)etc/docker/daemon.json

文章目录 如何更改docker默认存储路径&#xff1f;版本1&#xff08;没测试&#xff09;版本2&#xff08;可行&#xff09;1. 停止 Docker 服务&#xff1a;2. 创建新的存储目录&#xff1a;3. 修改 Docker 配置文件&#xff1a;4. 移动现有的 Docker 数据&#xff1a;5. 重新…

Java-svg格式的oss图片链接转换为png格式图片字节流

一、引入依赖 <!--svg转其他格式依赖--> <dependency><groupId>org.apache.xmlgraphics</groupId><artifactId>batik-transcoder</artifactId><version>1.14</version> </dependency> <dependency><groupId&g…

什么样的服务器是合乎直销网站标准

现在社会的发展,有着越来越多的人想要利用互联网来做直销。做好直销行业系统解决方案离不开好的服务器支持,服务器的的稳定性和速度是直接影响网站后期运作,可以看做是网站的根基。 做网站直销选择租用服务器需要注意的几点要素 一些大的直销互联网公司如安利、雅芳、康宝莱、玫…

【人工智能】自然语言处理(NLP)的突破,关注NLP在机器翻译、情感分析、聊天机器人等方面的最新研究成果和应用案例。

自然语言处理&#xff08;NLP&#xff09;作为人工智能的一个重要分支&#xff0c;近年来取得了显著的突破&#xff0c;特别在机器翻译、情感分析、聊天机器人等领域取得了显著的研究成果和广泛的应用。以下是对这些领域最新研究成果和应用案例的概述&#xff0c;并附带相应的代…

域名解析记录与服务器源IP的探索

在互联网中&#xff0c;域名和IP地址是进行网络通信的基础。用户通常通过域名来访问网站或服务&#xff0c;而实际的数据交换则发生在IP地址之间。域名解析&#xff08;DNS解析&#xff09;是将易于记忆的域名转换为计算机可识别的IP地址的过程。本文将探讨如何通过域名解析记录…

Uniapp自定义动态加载组件(2024.7更新)

1.本次介绍如何使用uniapp实现自定义动态加载Loading的组件&#xff0c;可以gif格式&#xff0c;也可以mp4格式等; 编写自定义Loading组件(CustomLoader.vue)&#xff1b;组件中含有“动态接收图片路径”&#xff0c;“10秒超时未false则自动断开关闭Loading”&#xff1b;在全…

【JavaScript 算法】广度优先搜索:层层推进的搜索策略

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理二、算法实现三、应用场景四、优化与扩展五、总结 广度优先搜索&#xff08;Breadth-First Search, BFS&#xff09;是一种用于遍历或搜索图或树数据结构的算法。该算法从起始节点开始&#xff0c;逐层向外扩展…

小程序-2(WXML数据模板+WXSS模板样式+网络数据请求)

目录 1.WXML数据模板 数据绑定 事件绑定 小程序中常用的事件 事件对象的属性列表 target和currentTarget的区别 bindtap的语法格式 在事件处理事件中为data中的数据赋值 事件传参与数据同步 事件传参 bindinput的语法绑定事件 文本框和data的数据同步 条件渲染 w…

《向量数据库指南》——使用 Grafana 和 Loki 搭建 Milvus Cloud日志查询系统

本教程将介绍如何设置 Grafana 和 Loki 来有效监控您的 Milvus Cloud实例。 Milvus Cloud是一款分布式向量数据库,可高效存储、索引和管理万亿级 Embedding 向量,是搭建 AI 和 ML 应用的首选向量数据库系统。 Grafana 是一个开源的指标监控平台,提供可视化的指标和日志…

5,SSH 端口转发

SSH 端口转发 简介 SSH 除了登录服务器&#xff0c;还有一大用途&#xff0c;就是作为加密通信的中介&#xff0c;充当两台服务器之间的通信加密跳板&#xff0c;使得原本不加密的通信变成加密通信。这个功能称为端口转发&#xff08;port forwarding&#xff09;&#xff0c…

SpringCloud | 单体商城项目拆分(微服务)

为什么要进行微服务拆分&#xff1f; 在平常的商城项目中&#xff0c;我们一般的项目结构模块都是将各种业务放在同一个项目文件夹&#xff0c;比如像&#xff1a; 用户&#xff0c;购物车&#xff0c;商品&#xff0c;订单&#xff0c;支付等业务都是放在一起&#xff0c;这样…

thinkphp:数据库多条件查询

一、使用if条件限制查询条件 $query Db::table(wip_operation_plan)->alias(d)->join([wip_jobs_all > a], a.wip_entity_name d.wip_entity_name)->join([sf_item_no > c], a.primary_itemc.item_no)->field(d.*,c.item_no as item_no,c.item_name as i…

线上观看 3 万+!「智能运维MeetUp」精彩回顾,探讨智能体构建新方向

龙蜥社区“走进系列”第 11 期走进中兴通讯-智能可观测运维技术 MeetUp 于成都圆满结束&#xff0c;由中兴通讯联合龙蜥社区系统运维联盟&#xff08;SOMA&#xff09;&#xff08;以下简称“联盟”&#xff09;共同举办。本次活动现场汇聚了阿里云、谐云科技、乘云数字、中兴通…

MySQL数据库day7.11

一&#xff0c;SQL概述 1.1 SQL语句语法 MySQL 数据库的 SQL 语句不区分大小写&#xff0c;关键字建议使用大写&#xff0c; 以分号结尾。例如&#xff1a; SELECT * FROM user; 使用 /**/ 、 -- 、 # 的方式完成注释 /* 多行注释 */ -- 单行注释 # 单行注释 SELECT * FRO…

vue2 ant-design select组件自定义下拉框, dropdownRender 使用,以及遇到的坑

业务需求&#xff1a;下拉框需要满足用户可输入筛选 和 点击右侧 字符按钮 #A-Z进行用户选择 1、基础页面代码 <div><a-selectstyle"width: 100%"placeholder"请选择客户"allow-clearshow-search:filter-option"false":not-found-con…

计算机硬件---如何更新自己电脑的BLOS

1找官网 例如“我使用的是HP&#xff08;惠普&#xff09;品牌的电脑”我只需要在浏览器上搜索“惠普官网”或“惠普-blos更新” 就可以看到&#xff0c;来自官网中更新blos的信息 2.有些品牌要查序列号该怎么办呢&#xff1f; 有许多方法可以查询&#xff0c;例如&#xf…