C++杂谈
文章平均质量分 66
随便聊聊C++相关的各种问题
HUSTER593
这个作者很懒,什么都没留下…
展开
-
安全执行部分逻辑工具类实现
【代码】安全执行部分逻辑工具类实现。原创 2024-03-25 14:38:45 · 152 阅读 · 0 评论 -
C++项目中如何处理内存碎片?
了解和应用这些策略,可以有效地处理内存碎片问题,优化程序的性能和稳定性。:内存碎片大致分为两类,外部碎片和内部碎片。转载 2023-11-21 19:57:56 · 207 阅读 · 0 评论 -
C++教程笔记链接推荐
the cherno cpp series 1the cherno cpp series 2Effective C++学习笔记原创 2023-10-24 17:00:43 · 201 阅读 · 0 评论 -
windows 环境下,可执行 exe 文件和 .dll 文件在不同目录下的处理办法
LoadLibrary 函数会搜索一系列的文件路径来查找指定的 .dll 文件,因此你可以将 .dll 文件的路径添加到这些路径中,以确保 .dll 文件可以被找到。需要注意的是,使用动态加载的方式加载 .dll 文件需要在程序运行时进行,因此需要在适当的时机调用 LoadLibrary 函数来加载 .dll 文件,以确保 .dll 文件可以被找到并正确地使用。如果你需要在 .dll 文件中使用其他的 .dll 文件,那么可以通过调用 SetDllDirectory 函数来添加其他的文件路径。原创 2023-04-25 10:30:13 · 4759 阅读 · 1 评论 -
三说 拷贝构造之禁用
关于C++的拷贝构造函数,很多的建议是直接禁用。为什么大家会这么建议呢?没有拷贝构造函数会有什么限制呢?如何禁用拷贝构造呢?这篇文章对这些问题做一个简单的总结。这里讨论的问题以拷贝构造函数为例子,但是通常赋值操作符是通过拷贝构造函数来实现 的( copy-and-swap 技术,详见《Exceptional C++》一书),所以这里讨论也适用于赋 值操作符,通常来说禁用拷贝构造函数的同时也会禁用赋值操作符。关于拷贝构造函数的禁用原因,我目前了解的主要是两个原因。第一是浅拷贝问题,第二 个则是基类拷贝问题。编原创 2022-06-20 16:33:23 · 1079 阅读 · 0 评论 -
C++中一种仅包含头文件就能进行单元测试的方法
文章目录1. gtest的问题2. 现代C++ unit test库3. doctest基本用法4. doctest的断言宏5. 现代C++ mock库6. 现代C++ benchmark库1. gtest的问题gtest需要安装有时候带来很多不方便,比如需要经常切换gcc和clang的时候就比较麻烦,安装的gtest可能在另一个编译器下编译不过, 编写跨平台程序的时候需要多次安装gtest,非常不便。另外一个问题是网络原因,下载安装gtest或者git上拉gtest都可能因为网络原因失败。2. 现代转载 2022-05-19 09:31:05 · 2756 阅读 · 0 评论 -
Windows 下编程,关于导入导出的一些验证和说明
文章目录场景一:声明和实现都在 `.h` 文件中时,给外部模块用,需不需要导入导出 ?场景二:声明和实现分开在 `.h` `.cpp`文件中时,给外部模块用,需不需要导入导出 ?场景三:声明和实现分开在 `.h` `.cpp`文件中时,给外部模块用,只导出需要的函数接口行不行 ?场景四: 给外部使用的枚举需要显式导入导出么?常量需要导入导出么?释疑与总结题外话通常情况下,开发者在用到 __declspec(dllexport) 和 __declspec(dllimport) 时,大多数是为了本模块的接口供原创 2022-05-10 15:28:22 · 2338 阅读 · 0 评论 -
在C++编程中最常见的几种犯错类型
文章目录1、有些关键字在cpp文件中多写了2、函数参数的默认值写到函数实现中了3、在编写类的时候,在类的结尾处忘记添加";"分号了4、只添加了函数声明,没有函数实现5、cpp文件忘记添加到工程中,导致没有生成供链接使用的obj文件6、函数中返回了一个局部变量的地址或者引用7、忘记将父类中的接口声明virtual函数,导致多态没有生效8、该使用双指针的地方,却使用了单指针9、发布exe程序时,忘记将exe依赖的C运行时库和MFC库带上10、应该使用深拷贝,却使用了浅拷贝IT公司每年都会有一定的人员流动,相应转载 2022-04-28 15:08:23 · 245 阅读 · 0 评论 -
重载、覆写与多态 小例
如果派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,那么就会遮蔽从基类继承过来的成员。所谓覆写,就是在派生类中使用该成员(包括在定义派生类时使用,也包括通过派生类对象访问该成员)时,实际上使用的是派生类新增的成员,而不是从基类继承来的。基类成员和派生类成员的名字一样时会造成遮蔽,这句话对于成员变量很好理解,对于成员函数要引起注意,不管函数的参数如何,只要名字一样就会造成遮蔽。换句话说,基类成员函数和派生类成员函数不会构成重载,如果派生类有同名函数,那么就会遮蔽基类中的所有同名函数,不管它们的参原创 2022-03-17 10:30:16 · 198 阅读 · 0 评论 -
手写一个sharedPointer
class SharedCount { public: SharedCount() : count_{1} {} void add() { ++count_; } void minus() { --count_; } int get() const { return count_; } private: std::atomic<int> count_; }; template<typename T> cla.原创 2022-02-14 16:35:54 · 263 阅读 · 0 评论 -
上行转换与下行转换
【格式】:dynamic_cast < type-id > ( expression)该运算符把expression转换成type-id类型的对象。Type-id可以是类的指针、类的引用或者void*。如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。【作用】:将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理, 即会作出一定转载 2022-01-25 12:51:59 · 1664 阅读 · 0 评论 -
SDK发布包中API兼容性问题及跨版本问题说明
目录1 版本兼容问题1.1 兼容性级别1.1.1 向后兼容性1.1.1.1 功能性兼容性1.1.1.2 源代码兼容性1.1.1.3 二进制兼容性1.1.2 向前兼容性1.2 怎么维护向后兼容性1.2.1 添加功能1.2.2 修改功能1.2.3 弃用功能1.2.4 移除功能2 跨平台问题1 版本兼容问题1.1 兼容性级别通常应该为 API 的“主、次和补丁”版本提供不同级别的兼容性承诺。例如,可以承诺补丁版本同时满足向后和向前兼容,或者承诺只有主版本才会破坏二进制兼容性。1.1.1 向后兼容性向后兼原创 2021-12-21 19:31:40 · 2435 阅读 · 0 评论 -
深入理解结构体指针、函数指针、多级指针
目录指针变量解引结构体指针强制类型转换void 指针函数指针函数指针使用函数指针应用回调函数多级指针多级指针的应用作者一直觉得C语言较其他语言最伟大的地方就是C语言中的指针,有些人认为指针很简单,而有些人认为指针很难,当然这里的对简单和难并不是等价于对指针的理解程度。为此作者在这里对C语言中的指针进行全面的总结,从底层的内存分析,彻底让读者明白指针的本质。作者认为C指针应该和C语言中的变量放在一起,因为C指针本质上还是一个变量,但现在大部分教材将其单独拿出来讲解,这也使得很多初学者认为指针是一个和变量转载 2021-12-10 14:59:20 · 2087 阅读 · 1 评论 -
C++中指针的引用*&
如指针一样,指针的引用容易使人困惑。我们注意到类似下面这种语法void func(int *&x){ ++x;}我猜你可能对int *&x有点疑惑。这叫做指针的引用。int *&x不要觉得看着复杂,其实一点也不复杂。我帮你拆开来看:按照C++程序员的习惯,指针“*”号是和类型放在一起的。C++中&是引用符号。我们需要注意的是“引用”不产生副本,而是给原变量起别名。对引用操作就是对原变量操作。所以只需要这样:int* &x一目原创 2021-11-10 14:55:36 · 1846 阅读 · 0 评论 -
C/C++内存管理
C 语言内存管理指对系统内存的分配、创建、使用这一系列操作。在内存管理中,由于是操作系统内存,使用不当会造成毕竟麻烦的结果。本文将从系统内存的分配、创建出发,并且使用例子来举例说明内存管理不当会出现的情况及解决办法。一、内存在计算机中,每个应用程序之间的内存是相互独立的,通常情况下应用程序 A 并不能访问应用程序 B,当然一些特殊技巧可以访问,但此文并不详细进行说明。例如在计算机中,一个视频播放程序与一个浏览器程序,它们的内存并不能访问,每个程序所拥有的内存是分区进行管理的。在计算机系统中,运行程序原创 2021-10-24 12:15:13 · 119 阅读 · 0 评论 -
C++ Implement的使用 | 消除 warning C4251
在编写C++动态库的过程中,我们常常会听到某个要求:请隐藏动态库头文件里类接口里的成员变量!或者自己在编写动态库时,突然意识到自己好像让调用者看到的信息太多了,而这些信息根本无需被调用者看到,往往调用者只需要接口函数而已,所以给他们接口函数就可以了。暴露动态库头文件类接口里的成员变量有很多坏处: 1、增加头文件更新次数。如果成员变量不被隐藏,则每次修改成员变量都需要给调用者更新头文件。 2、暴露给用户太多信息。编写库的目的一个是方便,另一个就是私密性,让类的实现部分在用户端不可见,如果过多地暴露成转载 2021-08-18 14:44:24 · 1423 阅读 · 0 评论 -
glog源码剖析及优化
文章目录开始为什么HAVE_ALIGNED_STORAGE宏下面的代码可以直接构造对象呢?LOG(INFO)<<”xxx”<<”yyy”中,glog是如何收集到xxx和yyy数据的呢?将stream接收到的数据都存到了message*text*中,那数据是如何写到文件中去的并且是线程安全的呢?glog中日志写到文件中是什么时候Flush到磁盘中的呢?总结如何设计一个高效的log模块?muduo async log日志逻辑扩展每个开发者编程中都会记录log信息,多数人都会使用log第转载 2021-08-12 10:09:52 · 1891 阅读 · 0 评论 -
C/C++内存相关问题梳理
引言C 和 C++ 程序中的内存错误非常有害:它们很常见,并且可能导致严重的后果。来自计算机应急响应小组(请参见参考资料)和供应商的许多最严重的安全公告都是由简单的内存错误造成的。自从 70 年代末期以来,C 程序员就一直讨论此类错误,但其影响在至今年仍然很大。更糟的是,如果按我的思路考虑,当今的许多 C 和 C++ 程序员可能都会认为内存错误是不可控制而又神秘的顽症,它们只能纠正,无法预防。但事实并非如此。本文将让您在短时间内理解与良好内存相关的编码的所有本质:正确的内存管理的重要性存在内存错误的翻译 2021-08-09 10:16:55 · 1057 阅读 · 0 评论 -
GTest 总结
Google C++单元测试框架(简称Gtest),可在多个平台上使用(包括Linux, Mac OS X, Windows, Cygwin和Symbian),它提供了丰富的断言、致命和非致命失败判断,能进行值参数化测试、类型参数化测试、“死亡测试”。1断言一般的,要测试一个方法(函数)是否是正常执行的,可以提供一些输入数据,在调用这个方法(函数)后,得到输出数据,然后检查输出的数据是否与我们期望的结果是一致的,若一致,则说明这个方法的逻辑是正确的,否则,就有问题。 在对输出结果进行检查(chec.原创 2021-08-04 17:29:12 · 6941 阅读 · 0 评论 -
C++ 前置声明
问题最近遇到了两个类A、B相互调用的情况,于是想当然的在两个类A和B的头文件中 #include 了所需的头文件,当然结果编译报错了。为什么呢,A需要B,B需要A,形成了循环,违反了程序的确定性原则。代码如下图所示:如这样相互包含的问题,可以使用前置声明来解决。即:在头文件中声明该类,在实现文件中包含该类。如下图所示:解析为什么这样使用前置声明,即在AAA.h中声明class BBB; 在BBB.h中声明class AAA; 且成员变量写为所声明类的指针变量, 便不会产生相互包含的错误呢?原因原创 2021-08-04 11:36:54 · 1438 阅读 · 0 评论 -
二说 拷贝构造函数 && 拷贝赋值函数
文章目录什么是拷贝构造函数拷贝构造函数的调用时机2.1 当函数的参数为类的对象时2.2 函数的返回值是类的对象2.3 对象需要通过另外一个对象进行初始化浅拷贝与深拷贝3.1 默认拷贝构造函数3.2 浅拷贝3.3 深拷贝3.4 防止默认拷贝发生拷贝构造函数的几个细节4.1 为什么拷贝构造函数必须是引用传递,不能是值传递?4.2 拷贝构造函数的作用。4.3 参数传递过程到底发生了什么?4.4 在类中有指针数据成员时,拷贝构造函数的使用?4.5 拷贝构造函数里能调用private成员变量吗?4.6 以下函数哪个是原创 2021-07-27 17:12:13 · 1082 阅读 · 0 评论 -
一说 拷贝构造函数 && 拷贝赋值函数
特别说明:拷贝构造函数和拷贝赋值函数要成对出现移动构造函数和移动赋值函数也要成对出现拷贝构造函数是在对象被创建时调用的,而赋值函数只能在已经存在了的对象调用。看下面代码: String a("hello"); String b("world"); String c = a;//这里c对象被创建调用的是拷贝构造函数 //一般是写成 c(a);这里是与后面比较 c = b;//前面c对象已经创建,所以这里是赋值函数上面说明出现“=.原创 2021-07-26 20:49:49 · 281 阅读 · 0 评论 -
手把手教你如何制作和使用lib和dll
本文的内容经过本人亲自调试,确保可用,实用,测试环境为win10+vs2015+C++ 目录 静态库 什么是静态库? 怎么创建 如何使用 静态库的第一种使用方法 静态库的第二种使用方法 动态链接库 动态库是什么? 怎么创建 如何使用 隐式调用 显式调用 静态库 什么是静态库? 我们先来说一下什么是静态库,维基百科对其的解释是这样的: 在计算机科学里,静态库...转载 2021-06-18 17:31:44 · 2568 阅读 · 0 评论 -
#pragma pack() 释疑
1.#pragma简述在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma 指令对每个编译器给出了一个方法,在保持与 C 和 C++ 语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。2.#pragma pack的作用#pragma pack 的主要作用就是改变编译器的内存对齐方式,这个指令在网络报文的处理中有着重要的作用,#pragma pac原创 2021-05-13 10:45:46 · 3238 阅读 · 0 评论 -
C/C++ 中典型内存拷贝函数原理及示例
memcpyC 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。strcpyC 库函数 char *strcpy(char *dest, const char *src) 把 src 所指向的字符串复制到 dest。strncpyC 库函数 char *strncpy(char *dest, const char *src, size_t n) 把 src 所指向的字符串复制.原创 2021-02-05 11:49:54 · 1910 阅读 · 0 评论 -
关于结构体、类、联合体、位域等所占内存大小计算
结构体所占字节1Byte(字节)=8bit(位,二进制运算符),1KB=1024Byte,1MB=1024KB注意事项:如果代码中没有明确指定#pragma pack (n),则结构体按照size最大的成员进行对界如果代码中指定#pragma pack (n)的n大于结构体中最大成员size,则其不起作用,结构体仍然按照size最大的成员进行对界。其余如果指定#pragma pack (n),则按其作为对齐系数内存对齐双要素:结构体变量中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排原创 2021-02-05 11:43:23 · 2297 阅读 · 0 评论 -
C++典型习题demo
// 0. ===================================================/** * 在横线处添加 1到3行代码 * 使main执行时,屏幕输出"10,10" **/#include <iostream>using namespace std;class X{ int a; int b; union { int c; char d[4]; int e; };原创 2021-01-20 17:10:24 · 199 阅读 · 0 评论 -
C++11 温故知新
0 目录1 decltype && auto2 返回值类型后置3 using && typedef4 lambda匿名函数5 for循环6 constexpr7 右值引用8 移动构造函数9 move()函数:将左值强制转换为右值10 完美转发11 智能指针11.1 shared_ptr11.2 unique_ptr11.3 weak_ptr附录1 decltype && autodecltype (declare tpe) 和 auto 一样都是在编译期原创 2020-12-07 11:27:21 · 147 阅读 · 0 评论 -
现代C++语言(C++11/14/17)特性总结和使用建议
C++语言在历史上经过了很多次的演进。最早的时候,C++语言没有模板、STL、异常等特性,之后加入这些特性形成大多数人所熟悉的C++98/03标准。在此之后,C++经过10多年又孕育出了拥有众多革命性变化的C++11标准(在标准正式发布前,被称为C++0x)。C++11包括了约140个新特性和约600个缺陷的修正。由于其变化实在太大,被很多人称为“现代C++语言”(Modern C++ Language),以和之前的经典C++语言作区分。在C++11后,标准委员会又发布了C++14和C++17标准,其内容大原创 2020-12-05 22:42:06 · 5089 阅读 · 0 评论 -
IPV4地址与int类型之间的转换
0 前言IP地址(IPV4)是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节)。IP地址(IPV4)通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。例:点分十进IP地址(100.4.5.6),实际上是32位二进制数(01100100.00000100.00000101.00000110)。即ip 地址(IPV4)本身就是一个32位的二进制数,只是通常被以 a.b.c.d 的形式表示而已。1 为什么要转换其实就是时间换空间原创 2020-11-13 10:50:05 · 2153 阅读 · 0 评论 -
std::function与lambda表达式混用示例
std::function是一个函数包装器模板,最早来自boost库,对应其boost::function函数包装器。在c++0x11中,将boost::function纳入标准库中。该函数包装器模板能包装任何类型的可调用元素(callable element),例如普通函数和函数对象。包装器对象可以进行拷贝,并且包装器类型仅仅只依赖于其调用特征(call signature),而不依赖于可调用元素自身的类型。 一个std::function类型对象实例可以包装下列这几种可调用元素类型:函数、函数指原创 2020-10-09 20:28:58 · 939 阅读 · 1 评论 -
STL中常用容器操作时间复杂度小结
map, set, multimap, and multiset采用红黑树实现,红黑树是平衡二叉树的一种。不同操作的时间复杂度近似为:插入: O(logN)查看:O(logN)删除:O(logN)hash_map, hash_set, hash_multimap, and hash_multiset采用哈希表实现,不同操作的时间复杂度为:插入:O(1),最坏情况O(N)。查看:O(1),最坏情况O(N)。删除:O(1),最坏情况O(N)。vector从名字看,随机访问的复杂度应该是O原创 2020-09-27 17:59:20 · 5176 阅读 · 0 评论 -
C++中对break和continue的各种使用场景举例说明
break 作用:用于终止当前循环break 如果用于循环是用来终止循环,break只能终止距离它最近的循环break如果用于switch,则是用于终止switchbreak不能直接用于if中,除非if属于循环的一个句子,但此时它的作用是循环而不是ifcontinue 作用:用以跳过本次循环余下的语句,转去判断是否需要执行下次循环只作用于距离它最近的循环:for 、while 、do …whilecontinue也不能直接用于if中,除非if属于循环的一个句子,同break,此时它的原创 2020-09-27 15:40:51 · 1186 阅读 · 2 评论 -
泛型编程&&运算符重载——简单示例
# if 0// 函数模板template<typename T>T max(T a, T b, T c) { T max_num = a; if (b > max_num) max_num = b; if (c > max_num) max_num = c; return max_num;}// 类模板template<typename T1, typename T2> //这里不能有分号class Point{pub原创 2021-01-20 17:23:00 · 187 阅读 · 0 评论 -
到底是以成员函数还是全局函数的形式重载运算符?
例子//全局friend Complex operator+(const Complex &c1, const Complex &c2);//成员,记得加=号,“+=”Complex & operator+=(const Complex &c);对于全局函数形式的重载“+” 先来看b = a + 1.1;,实际上会被转换为b = operator+(a, 1.1);这样的形式进行调用;因为存在转换构造函数,并且第一个参数为 double,那么编译器就会将 1.转载 2020-09-23 16:11:01 · 1942 阅读 · 0 评论 -
C++ STL中Map的按Key排序和按Value排序
map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value。假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行存储就是个不错的选择。 我们这样定义,map<string, int>,其中学生姓名用string类型,作为Key;该学生的成绩用int类型,作为value。这...转载 2020-09-23 11:32:29 · 865 阅读 · 0 评论 -
从求解 1 + 2 + … + n 谈到逻辑符短路
目录1 问题描述2 解法2.1 平均计算2.2 迭代2.3 递归2.4 逻辑运算符的短路效应参考文档1 问题描述求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。示例 1:输入: n = 3输出: 6示例 2:输入: n = 9输出: 45题源:力扣 面试题642 解法2.1 平均计算public int sumNums(int n) { return (1 + n) * n /原创 2020-09-09 17:06:18 · 149 阅读 · 0 评论 -
浅谈下迭代器失效的几种情况
引言最近自己写代码用到了删除链表中某个节点操作,因为迭代器使用不规范,造成了程序崩溃。例如,对某个迭代器解引用所获得的值并不是执行erase()前这个迭代器指向的值,还有可能对未指向任何元素的迭代器的解引用赋值而引发程序crash。类似的问题代码像这样:LeetCode第283题的一种常规解法class Solution {public: void moveZeroes(vector<int>& nums) { int num = 0;原创 2020-08-27 17:52:48 · 509 阅读 · 0 评论 -
浅谈使用卫语句重构方法
卫语句定义:如果条件语句极其复杂,就应该将条件语句拆解开,然后逐个检查,并在条件为真时立刻从函数中返回,这样的单独检查通常被称之为“卫语句”(Guard Clauses)。说人话就是:写方法时在合适的时候尽快return,少用else按卫语句对函数进行重构应遵循:及时return,if中能return就return。(一旦满足条件return后你根本无需关注后面的代码)能够return的就尽量少使用else。(用else太多,读者需要维护大量的栈在大脑中)减少嵌套,一般嵌套超过4层读者就会产生原创 2020-08-12 10:26:24 · 1974 阅读 · 1 评论 -
简易字符串内存大小比较
示例#include <iostream>#include <string.h>using namespace std;int main(){ char *acx = "hello"; char acy[ ]= {'h','e','l','l','o' }; char acz[ ] = "hello"; char acu[8]= {'h','e','l','l','o' }; cout<<sizeof(acx)<<endl;原创 2020-08-05 17:09:32 · 641 阅读 · 0 评论