- 博客(197)
- 收藏
- 关注
原创 C++20之std::span:高效访问容器的神器
C++20引入了std::span作为一种语法糖,用于表示连续内存范围。它提供了一种轻量级的、非拥有式的、零开销的方式来引用数组或其他连续内存块。std::span可以用于传递数组片段给函数,或者在函数内部对连续内存进行操作,而无需进行内存拷贝。std::span提供连续对象序列的轻量级视图。 span 提供了一种安全的方法来对在内存中背靠背排列的对象进行迭代和索引。 例如存储在内置数组中的对象 std::array 或 std::vector。如果你通常使用指针和索引访问一系列背靠背对
2024-07-17 22:56:57
1168
27
原创 CTK框架(二): 接口、插件和服务
综上所述,CTK插件框架中的接口、插件、服务是三个紧密相关的概念,它们共同构成了一个可扩展、可复用的应用程序架构。通过这三个概念的灵活应用,可以构建出功能丰富、易于维护的生物医学图像计算应用程序。
2024-07-15 23:51:14
830
13
转载 CTK框架(一): CTK Plugin Framework简介
CTK Plugin Framework设计参考了OSGi(Open Service Gateway Initiative,开放服务网关协议)(Java的动态组件系统),并提供了一种能让应用程序(动态地)由许多不同的可重用组件组成的开发模型,允许通过服务进行通信。OSGi规范的核心部分是一个框架,核心框架定义了应用程序的生命周期模式和服务注册。
2024-07-14 22:20:23
64
9
原创 C++中跨平台类的设计方法
本文从类的设计角度来考虑代码的跨平台性,其实在实现的过程还需要综合考虑平台差异、标准库和第三方库的选择、运行时环境差异的处理、跨平台编译工具的使用、跨平台测试与调试以及跨平台接口设计等多个方面。通过合理的设计和实现,可以大大提高代码的可移植性和复用性,降低维护成本。
2024-07-14 18:35:54
761
6
原创 C++惯用法:do...while(0)的妙用
在C++中,通常是用来做循环用的,然而我们做循环操作可能用for和while要多一些。经常看到一些开源代码会出现这样的代码,这样的代码看上去肯定不是用来做循环的,那为什么要这样用呢?下面就讲讲使用它的好处。
2024-07-14 12:25:29
1323
2
原创 深入理解C++构造函数
在C++中,自定义构造函数允许你为类的实例提供特定的初始化逻辑。构造函数初始化列表是构造函数体之前的一个冒号()后跟一个以逗号分隔的初始化器列表。它用于初始化成员变量,特别是那些不能通过赋值来初始化的成员(如const成员、引用成员或没有默认构造函数的类类型的成员)。就属于自定义构造函数。构造函数是C++中非常重要的概念,它们用于在对象创建时初始化对象的成员变量。构造函数没有返回类型,并且其名称必须与类名相同。通过构造函数,可以确保对象在创建时处于有效的状态。
2024-07-14 11:22:45
809
1
原创 spdlog一个非常好用的C++日志库(八): 自定义格式化符号
在spdlog中,扩展自定义标志允许您根据自己的需求定义新的日志格式标志。这通过继承custom_flag_formatter类并实现其clone()和format(...)抽象方法来完成。以下是如何在spdlog中扩展自定义标志的详细步骤:步骤 1: 继承 custom_flag_formatter 类首先,您需要创建一个继承自spdlog::custom_flag_formatter的类。在这个类中,您将定义您的新标志的逻辑。步骤 2: 实现 clone() 方法。
2024-07-10 22:40:08
1136
11
原创 C++惯用法: 通过std::decltype来SFINAE掉表达式
SFINAE 技术,即匹配失败不是错误,英文Substitution Failure Is Not An Error,其作用是当我们在进行模板特化的时候,会去选择那个正确的模板,避免失败。 SFINAE一般用于函数重载和编译期间类型检查,标准库中很多type traits模板就是通SFINAE来实现的。 看个具体的例子: 核心的代码是在实例化check_has_member_id对象的时候,通过模板参数T的类型,决定了结构体中对象value的值。而value的
2024-07-09 21:46:12
1237
9
原创 spdlog一个非常好用的C++日志库(七): 源码分析之异常类spdlog_ex
标准库异常类(std::exception)系列,能满足大多数使用异常的场景,但对系统调用异常及错误信息缺乏支持。spdlog通过继承std::exception,扩展对系统调用的支持,实现自定义异常类spdlog_ex。spdlog_ex类声明很简单,在std::exception基础上添加了string类型的msg_成员,提供支持errno的构造函数。
2024-07-07 11:39:49
310
10
原创 深入理解Qt智能指针
Qt 智能指针是 Qt 框架中非常重要的特性之一,它们通过自动管理内存和资源,大大简化了 Qt 应用程序的开发和维护工作。开发者应根据具体需求选择合适的智能指针类型,并遵循相关的使用注意事项,以编写出更安全、更稳定的 Qt 应用程序。
2024-07-07 11:28:20
894
3
原创 spdlog一个非常好用的C++日志库(六): 源码分析之registry类
已经有了用于接收前端用户log消息的类logger,代表log消息的类是log_msg,后端写log消息到目标文件的类sink,格式化log消息为最终字符串的类formatter,解析pattern flag的类pattern_formatter等等。但似乎还存在一个问题:库的使用者,如何使用它们?每次使用时,可能需要先创建logger对象,然后通过logger对象来接收用户log消息。然而,当用户希望创建多个logger对象时,谁来组织logger对象?
2024-07-06 16:41:23
1109
4
原创 浅谈C++中的防御性编程
在实际开发中,防御性编程不仅仅是一个技术问题,更是一种编码思维和习惯的养成。以下是一些具体的实践建议:代码审查定期进行代码审查,发现潜在的错误和问题。通过集体智慧,可以提高代码的质量和健壮性。编写单元测试单元测试可以帮助验证代码的正确性,捕获边界条件和异常情况。编写全面的单元测试是防御性编程的重要组成部分。持续学习和改进防御性编程是一门需要不断学习和实践的艺术。通过阅读相关书籍、博客和参加技术讨论,可以不断提高自己的防御性编程水平。
2024-07-06 10:35:15
1630
6
原创 spdlog一个非常好用的C++日志库(五): 源码分析之线程池thread_pool
spdlog通过类模板thread_pool来表示线程池,用于异步logger:从前端用户线程接收log消息,存放到thread_pool的mpmc_blocking_queue缓存(多生产者-多消费者阻塞队列)中,然后用子线程组作为后端线程,取出log消息并调用注册的任务处理。实际上调用async_logger::backend_sink_it_将log消息写到sink目标。
2024-07-05 22:54:48
615
5
原创 C++模块化之内部类
在C++中,内部类(Nested Class)是一种相对不太常用但却非常强大的编程工具。就是在一个类内部定义另外一个类,注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。 注意:内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员,不管是public、protected、private。但是外部类不是内部类的友元。
2024-07-05 21:47:41
966
原创 spdlog一个非常好用的C++日志库(四): 源码分析之logger类
一个logger类对象代表一个日志记录器,为用户提供日志记录接口。包括哪些功能?基本功能:logger名称,用于唯一标识该logger日志等级接收用户日志消息的接口提供一个sink(目标文件)指针数组和formatter(格式化),用于转换格式串并写到目标文件线程安全错误处理高级功能:环形队列缓存最近消息,便于回溯自定义错误处理
2024-07-04 23:00:52
1020
5
原创 Qt读取ini格式配置文件的类设计
本文详细介绍了 Qt 中的 QSettings 类,包括初始化、读取、写入和删除配置信息的操作。还讲解了在整个系统中怎么去设计系统配置文件读取类 我们还介绍了 QSettings 的应用场景。通过合理使用类CShortWaveConfig,您可以轻松管理和存储应用程序的配置信息,提高应用程序的灵活性和可维护性。
2024-07-04 22:20:51
1205
3
转载 spdlog一个非常好用的C++日志库(三): 源码分析之formatter类
spdlog并未说明何为scope(范围),何为pad(垫片)。在这里,我把要显示的一个固定宽度的pattern flag(形如"%8X" "%-8X" "%=8!X")称为scope,没有指定宽度的称为null-scope,进行填充动作的类称为padder(垫片器,填充器),包含填充信息的类为padding_info。一个pattern flag是一个模式标记,对应一个要显示的字段,当该字段的宽度固定时,如果固定宽度 > 实际显示宽度,就需要填充;
2024-07-03 22:06:21
94
5
原创 深入理解C++中的锁
C++标准库提供了多种类型的互斥锁,每种锁都有其特定的用途和特点。选择合适的互斥锁类型可以有效提高程序的并发性能和安全性。C++惯用法之RAII思想: 资源管理_raii 思想-CSDN博客。
2024-07-02 23:15:03
1262
9
转载 spdlog一个非常好用的C++日志库(二): 源码分析之sinks系列类
sinks并不是一个类,而是一系列类,以基类-派生类形式组织,一个sink派生类代表了一种输出log消息方式,输出目标可以是普通文件stdout、stderr,或者syslog等等。sink系列类主要负责从logger接收用户log消息,按指定模式(pattern)进行格式化(format),得到一条完整的、格式化后的log消息,然后将其写到目标文件。sink系列类的实现,全部位于include/spdlog/sinks目录。
2024-06-27 22:59:23
146
11
原创 STL中的迭代器模式:将算法与数据结构分离
STL 中的算法是一组函数模板,它们接受迭代器作为参数,并对迭代器范围内的元素执行操作。这些算法包括排序、搜索、复制、删除等操作。由于算法是独立于数据结构的,因此它们可以与任何支持迭代器接口的容器一起使用。通过将算法与容器分离,STL 允许程序员根据需要组合不同的算法和容器。例如,你可以使用排序算法对向量进行排序,或者使用搜索算法在集合中查找元素。这种灵活性使得 STL 能够适应各种不同的应用场景。总的来说,STL 的设计方式通过将算法与数据结构分离,实现了代码的可重用性、可维护性和灵活性。
2024-06-27 22:15:07
978
7
原创 为什么变量不可以在 switch 语句中声明定义?
变量不能在switch语句中声明定义的主要原因是作用域和跳转语句的限制。为了避免潜在的作用域冲突和未定义行为,我们应该在switch语句之前声明所有必要的变量,或者使用花括号在case分支中创建新的作用域(在支持C99或更高标准的编译器中)。通过遵循这些最佳实践,我们可以确保代码的清晰性和稳定性。
2024-06-26 08:18:34
680
15
原创 C++之thread_local变量
thread_local 是 C++11 为线程安全引进的变量声明符。表示对象的生命周期属于线程存储期。线程局部存储(Thread Local Storage,TLS)是一种存储期(storage duration),对象的存储是在线程开始时分配,线程结束时回收,每个线程有该对象自己的实例;如果类的成员函数内定义了 thread_local 变量,则对于同一个线程内的该类的多个对象都会共享一个变量实例,并且只会在第一次执行这个成员函数时初始化这个变量实例。
2024-06-21 20:14:14
1260
15
原创 spdlog一个非常好用的C++日志库(一): 简介与使用
spdlog是一个开源的C++日志库,它提供了高性能和易用性的日志记录功能。它是为了满足现代C++应用程序的需要而创建的,可以在不同的平台上运行。spdlog 是一个快速、异步的、header-only 的 C++ 日志库。它提供了简单易用的 API 并具有高性能和可扩展性。spdlog因其高性能、易用性和丰富的功能,在C++开发中常被用作日志记录工具,帮助开发人员更好地追踪代码执行、排查问题、分析性能等。
2024-06-20 23:30:39
1711
8
原创 C++之std::type_identity
std::type_identity是 C++17 引入的一个实用工具,用于确保类型别名保持其引用的完整性。在某些模板元编程的场景中,尤其是在与类型萃取(type traits)和完美转发(perfect forwarding)相关的场景中,保持类型的“原样”传递是非常重要的。 std::type_identity是一个简单的模板,它定义了一个别名type,该别名简单地重新声明了其模板参数类型。但重要的是,它不会修改或“破坏”传递给它的类型。
2024-06-18 22:57:15
1010
14
原创 Folly,一个强大的C++库
Folly库是一个强大而且广泛应用于Facebook的C++库,通过提供高效、可扩展和易用的工具和组件,帮助开发者构建高性能的C++应用程序。本文对Folly库的主要特点进行了详细介绍,并通过示例代码展示了其在实际项目中的应用。希望读者能够通过本文对Folly库有更深入的了解,并在自己的项目中充分发挥其优势,提升代码效率和可扩展性。
2024-06-18 08:29:45
834
11
原创 Qt实现单例模式:Q_GLOBAL_STATIC和Q_GLOBAL_STATIC_WITH_ARGS
} \从上述代码可以看出:1)根据不同的 NAME,生成了不同的命名空间,虽然对象创建函数、多线程同步变量guard的名字一样,但是是在不同的命名空间,因此生成的QGlobalStatic也是不一样的,其实这个也是实现技巧。2)QBasicAtomicInt 是 原子操作,是线程安全的,它的介绍在这里就不在赘述了,不明白的地方请自行查阅。3)Q_GLOBAL_STATIC是Q_GLOBAL_STATIC_WITH_ARGS的特例。
2024-06-16 23:38:56
1127
13
原创 C++模板之模板成员函数不能偏特化
好了,本篇小文就写到这里,总结一下内容,首先实例代码讲解了很多 C++ 书籍都提到,但是没有细说的:“虽然类模板可以偏特化,但是类模板的成员函数不可以偏特化” 这句话的意思,然后又介绍了两种利用函数重载机制实现的变相函数“偏特化”的方法。
2024-06-16 12:23:57
1069
9
原创 接口和抽象类:如何使用普通类模拟接口和抽象类
不同的编程语言对接口和抽象类的定义方式可能有差别,但差别并不会很大。因为Java既支持抽象类,又支持接口,所以我们使用Java进行举例讲解,以便读者对这两个有直观的认识。首先,我们看一下如何在 Java 中定义抽象类。下面这段代码是一个典型的抽象类使用场景(模板设计模式)。Logger 是一个记录日志抽象类,FileLogger 类和 MessageQueueLogger 类继承 Logger 类,分别实现不同的日志记式:将日志输出到文件中和将日志输出到消息队列中。
2024-06-16 11:54:56
975
4
原创 C++之assert惯用法
总之,assert是一种在开发过程中快速检测程序错误的有效工具,但在发布的产品代码中通常被禁用以避免性能影响。开发者可以根据需要使用assert或其他错误处理机制来确保程序的正确性和健壯性。
2024-06-11 21:00:58
984
27
原创 C++11原子操作
C++原子操作提供了一种高效、安全的多线程数据访问方式,在性能和安全性方面具有显著优势。通过合理使用std::atomic类和内存序选项,开发者可以编写出高效、可靠的多线程程序。
2024-06-06 23:12:37
1322
20
原创 C++之对象封装
面向对象编程是一种非常广泛的编译方式,很多开发者可能对它是既了解又不了解。对一些基础的知识会用,但又不知道是否用得合适,能不能有一个标准来判定。其实这恰恰表明对面向对象编程还是掌握的不够深入。一切设计没有标准只有原则,这也意味着,实际场景下,在考虑原则的同时,更要考虑实际的需求进行适当的取舍。最好的设计方法是没有的,只有最合适的设计方法。
2024-06-05 22:21:28
881
10
原创 免费开源图片转文字识别软件:Umi-OCR
Umi-OCR:免费,开源,可批量的离线OCR软件,目前适用于 Windows7 x64 及以上。这个项目基于基于 PaddleOCR,支持截图识别、批量导入识别、个性化识别等功能。整个项目由 python 语言编写,win7系统的小伙伴大概率是用不了的。推荐 Win10 x64 及以上版本。
2024-06-05 21:59:41
1054
2
原创 C++之noexcept
综上所述,C++11通过引入noexcept关键字、智能指针、移动语义等特性,以及增强STL和其他库,显著提高了C++的异常安全性。这些特性使程序员能够更好地管理资源、避免资源泄漏和未定义行为,并在异常发时代码的健壮性和可靠性。noexcept。
2024-06-04 23:14:16
820
10
原创 哪些代码看似面向对象编程风格,实则面向过程编程风格
还有一种在面向对象编程中常见的面向过程编程风格的代码:数据定义在一个类中,而方法定义在另一个类中。读者可能认为,这么明显的面向过程编程风格的代码,谁会这样写呢?实际上,如果读者基于 MVC三层结构进行 web项目的后端开发,那么这样的代码几乎天天都在写。传统的 MVC结构分为Model层、View层和Controller层。
2024-06-03 23:17:39
775
11
原创 C++17之std::void_t
std::void_t 可以用来判断一个类型 T 是否嵌套定义了某个类型。判断的原理就是利用 T::SomeType 类型的存在性,转化成 std::void_t 定义的合法性。
2024-06-02 22:04:27
857
10
原创 C++ 的 Tag Dispatching(标签派发) 惯用法
总结来说,Tag Dispatching在C++中主要用于实现泛型算法的优化、迭代器类型的优化、类型属性的判断、编译时条件判断、模板元编程以及类型安全的接口设计等方面。通过使用Tag Dispatching技术,可以根据参数类型或特性在编译时选择最优的实现路径,从而提高代码的性能和可维护性。标签派发C++之多层 if-else-if 结构优化(二)C++17之std::invoke: 使用和原理探究(全)
2024-06-02 16:53:56
1220
3
原创 C++模板为何通常定义在头文件中?
C++模板的强大之处在于它们的类型灵活性和编译时实例化。然而,这些特性也带来了一些特殊的编译和链接考虑。将模板定义放在头文件中是确保所有使用模板的编译单元都能看到完整定义的有效方法,从而避免了分离编译问题。虽然这种做法可能会增加编译时间和头文件的大小,但它确保了模板的正确性和可用性。在编写和使用模板时,了解这些编译和链接细节是至关重要的,因为它们直接影响到代码的结构、可维护性和性能。
2024-05-31 19:29:30
964
7
原创 Qt 插件机制使用及原理
Qt插件机制是一种强大且灵活的功能扩展方式,它允许开发者通过创建和加载插件来增强Qt应用程序的功能。通过遵循一定的规范,开发者可以轻松地创建和使用插件,从而满足各种复杂和多变的需求。
2024-05-29 23:44:45
1322
10
原创 基于接口而非实现编程:有没有必要为每个类都定义接口
这样的接口设计新没有意义了,不过,如果读者认为这种思考方式顺畅,那么可以接受, 但要注意,在将实现类中的方法搬移到接口定义中时,要有选择性地进行搬移,不要搬移与具体实现相关的方法,如AliyunImageStore类中的generateAccessToken()方法就不应该被搬移到接口中。上游系统面向接口而非实现编程,不依赖不稳定的实现细节,这样,当实现发生变化时,上游系统的代码基本不需要做改动,以此降低代码的耦合性,提高代码的扩。在本节最终重构之后的代码中,尽管我们通过接口隔离了两个具体的类现。
2024-05-28 23:33:41
719
9
浮点数与十六进制转换工具
2024-01-22
C++设计模式例程,工厂模式例子
2024-01-15
高质量 C++编程指南,编程的好书籍
2023-12-26
C++模板函数重载规则详解
2023-12-26
sscom 串口调试工具
2023-12-20
NetAssist 网络调试工具
2023-12-20
基于C++CORBA高级编程
2023-12-13
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人