1. C/C++
文章平均质量分 58
C++
Lzg_na
这个作者很懒,什么都没留下…
展开
-
C++线程互斥加锁总结
更新中本文将多线程中的一些加锁部分抽取出来深入学习,C++11部分有了一些崭新的库,C++17又支持了共享互斥锁。而C++98更偏向于C语言的方式,所以将C和C++区分开展示案例。原创 2024-08-10 16:18:55 · 878 阅读 · 0 评论 -
字符串hash算法
【代码】字符串hash算法。原创 2024-08-02 09:27:19 · 434 阅读 · 0 评论 -
IPV6地址
前言 IPV6地址的出现是为了解决IPV4地址缺乏的问题。 典型的IPV4地址所表示的IP地址数量很有限。比如102.165.220.124,使用了4个字节来表示,但四个字节独立,所以其理论上最多能表示的地址数量为255*255*255*255.1. IPV6地址表示方法 ipv6地址总共有128位,共16个字节。和IPv4地址一样,IPv6地址也可以用一串字符表示。IPv6地址,分成8块,每块2字节,使用16进制表示。如下所示:2. 化简原则全0块“0000”,可以化简为0多个全0原创 2022-02-27 23:19:40 · 5062 阅读 · 0 评论 -
memcpy和memmove
二者的区别在于memmove拥有缓冲区,而memcpy没有。由于没有缓冲区,会带来常说的安全问题。注意,在这里说的安全与否是指:目的地址是不是我们起初想要的数据,而不关心经过拷贝后源地址数据是否改变。在第一种情况下,二者都是从src拷贝到dest,这时两者都是安全的。第二种情况时,使用memcpy由于dst是src的一部分。开始拷贝时src的内容就被改变了,所以src的最后几个数据被销毁了。但使用memmove会先把数据读到自己的缓冲区,即使src的最后几个被覆盖了,源数据还在缓冲区中。.原创 2021-11-24 21:18:16 · 650 阅读 · 0 评论 -
算数左移、逻辑左移、移位操作 >>和>>>
目录前言1. 二进制表示2. 正数移位3. 负数移位4. 逻辑移位 和 算数移位前言 在进行移位操作时,对于无符号的左移和右移总是比较容易理解,无符号数的二进制表示也比较容易理解,但在进行有符号数的左移和右移时就可能产生一些问题。1. 二进制表示已正负3为例:(为表示方便,高三个字节省略)原码:+3:0000 0011-3:1000 0011反码:负数符号位不变,其余取反+3:0000 0011-3:1111 1100补码:正数不变,负数在反码基础上 +1+3:00原创 2022-02-12 16:42:19 · 957 阅读 · 0 评论 -
弱符号__attribute__((weak))
这个不太好解释,C的代码中出现同名的函数时,编译器会报函数重定义错误。弱符号的出现允许同名函数存在,弱符号告知链接器该函数或变量优先级较低,优先链接其他同名函数。原创 2023-05-24 22:24:14 · 989 阅读 · 0 评论 -
C陷阱和缺陷
2. 语法陷阱2.1 运算符优先级看上去琳琅满目,但有规律可循:优先级最高为括号、后缀、下标这一类单目运算符 的优先级仅次于上述, 高于双目运算符。双目运算符:算数运算符 ->移位运算符 ->关系运算符 ->逻辑运算符 ->赋值运算符 ->条件运算符单目运算符、赋值运算符和三目运算符的结合顺序是自右向左,其余都是自左向右举例:*p++会是*(p++) :自右向左结合while(c=get(in) != EOF)有错,赋值运算符优先级低,结合有错,应为原创 2022-02-12 15:34:45 · 830 阅读 · 0 评论 -
__attribute__ ((packed))
【代码】__attribute__ ((packed))原创 2023-05-24 22:36:47 · 369 阅读 · 0 评论 -
1. protobuf学习
ProtoBuf是中立于编程语言和编程平台的,可扩展的用于序列化结构化数据的解决方案,是Google公司开发的一种数据描述语言,可用于数据存储、通信协议等方面。定义完你所需要的数据结构后,你可以基于protoBuf生成各种语言的代码,这些定义的数据流可以轻松地被传递且不会破坏你已有的程序。并且你也可以更新你的结构体而现有的代码也不会收到任何影响。protoBuf目前支持Objective-C、C++、C#、Jave、Python、Go、PHP、JavaScript等主流语言。原创 2024-08-01 16:14:08 · 747 阅读 · 0 评论 -
C++智能指针
unique_ptr:内存的所有者必须是唯一的。如果进入不同的模块或者调用者,那么执行所有权转移。shared_ptr: 内存由多个指针变量共同使用,共同拥有内存的所有权。但是必须杜绝循环拷贝.weak_ptr: 对内存的使用仅仅是访问而已,不涉及其生命周期的管理。转载 2024-07-06 17:57:50 · 48 阅读 · 0 评论 -
C++ decltype类型
当使用decltype(var)的形式时,decltype会直接返回变量的类型(包括顶层const和引用)随着程序越来越复杂,程序中用到的类型也越来越多,我们有时候不得不去翻阅大量上下文去寻找此。会返回对应的函数类型,不会自动转换成相应的函数指针,需要添加一个。并不会实际计算表达式的值,编译器分析表达式并得到它的类型。就是一种类型说明符,它的出现主要是解决复杂的类型声明。原创 2023-09-28 16:19:09 · 307 阅读 · 0 评论 -
C和C++中的bitset
C/C++中没有bool类型,使用整形值表示bool类型占内存较多。C++中推出了bitset类库来,可以使用一个bit位来表示一个数据的bool类型,本文将有所介绍。另外在C语言中借助字符数组或整形值数组,同样可自己表示出bitset的机制。//声明一个长度为4bit的 bitset,默认每一位为 0. bitset < 8 > b(12);原创 2022-10-29 16:29:37 · 1652 阅读 · 2 评论 -
std::bind用法
C++11中的bind()函数是用来提供可调用函数对象和函数调用的参数绑定关系的。其可以支持普通函数、函数对象和成员函数的绑定,而且支持占位。原创 2022-10-03 14:45:25 · 1596 阅读 · 0 评论 -
std::function
函数模板std::function是一种通用、多态的函数封装。std::function可以存储和调用任何可调用的目标。原创 2022-08-24 20:37:55 · 1002 阅读 · 2 评论 -
函数指针的使用方法
一、C++函数指针如果我们在程序中定义了一个函数:int Max(int x, int y) //定义Max函数{ if (x > y) return x; else return y;}那么函数名Max就是调用这个函数的入口地址。就如同定义一个数组,这个数组名就是这个数组的首地址。既然是地址,就可以使用一个指针来指向它。对应于int Max(int x, int y),我们定义的函数指针如下:int(*p)(int, int);与函数声明类似,int(原创 2020-08-10 21:51:03 · 14638 阅读 · 0 评论 -
jsoncpp判断key是否存在以及类型
简单地说,可以用进行判断存在与否,类型需要使用具体判断:转载 2022-07-02 13:11:16 · 1536 阅读 · 0 评论 -
数据结构用C++实现堆排序
堆排序对于一个数组,总能用完全二叉树的方式去理解他,例如对于数组,536604248可以表示为完全二叉树如下536604248初始化堆堆就是,root节点总是比他的两个子节点的值要大,从最后一个非叶子节点(len/2-1)开始进行堆调整,本例是从第二个6开始,其下标正好也必然是len/2-1,若发现其子节点有大于当前节点的,则将最大的子节点与当前节点进行交换,进行一步交换形成二叉树:536804246当然实际上是数组中数的值在改变。需要注意的是,在调整的过程原创 2020-06-10 16:39:23 · 293 阅读 · 0 评论 -
设计模式9——抽象工厂
动机 在软件设计中经常面对一系列相互依赖的对象的创建工作,由于需求变化,经常面对更多对象的创建工作。1. 引入问题代码如下:class EmployeeDB{public: vector<EmployeeInfo> GetEmployee() { /* 创建SQL对象,建立初始网络连接 */ SqlConnect *connection = new SqlConnection(); connection->ConnectNet("ip:192.168.0.1"原创 2022-03-21 23:41:14 · 757 阅读 · 0 评论 -
Stub打桩UT测试
文章目录前言1. 使用方法1.1 想要测试的函数1.2 编写TEST_F前言 Stub用于在进行单元测试时,自己所写的函数调用的依赖的函数。但是这个依赖的函数在进行测试时可能无法得到我们想要的结果,就可以使用Stub.1. 使用方法1.1 想要测试的函数/* 功能:判断一个数是否大于100 返回值:0,不大于100 1,大于100 */int fun_greater100(int a){ if(check(a) <= 100){ return原创 2022-03-12 21:36:06 · 2029 阅读 · 0 评论 -
C++类对象单元测试中的Mock使用
文章目录前言1. 下载网址2. 为什么选择Google Mock3. C++简单的例子3.1 使用流程4. 指定自己的期望前言 在进行单元测试时,我们想要测试自己缩写函数A,但是函数A却依赖于函数B,当函数B无法满足预期时就无法对函数A进行测试,主要由于下面几个原因:函数B依赖于硬件设备真实的函数B的返回值无法满足我们的预期团队开发中函数B尚未实现 这时就需要对函数B进行打桩(仿真mock),使其达到我们预期的效果。但是如同下面这种类型函数时,则需要深入下去,对基层的函数进行打桩:t原创 2022-03-12 00:25:23 · 9374 阅读 · 0 评论 -
1、可变参数实现
前言 在C语言中说到可变参数,其实大家最熟悉的printf()函数就是可变参数。因为我们不仅可以单单打印字符串:printf("Helloworld!\n");还可以使用他来输出数值:int num = 0;printf("Hello, %d\n", num);1. 举例#define LOG(format, ...)\ {\ printf("%s, %d" format, __FUNCTION__, __LINE__, ##__VA_ARGS__);\ }其实 `__VA原创 2022-03-07 00:08:37 · 668 阅读 · 0 评论 -
利用位运算进行数值交换
程序void swap(int &a, int &b){ a ^= b;//异或 b ^= a; a ^= b;}逻辑找出a和b中不同的位,赋1b中不同的位:与1异或取反,与0异或还是本身此时b是原来的a。a中不同的位:与1异或取反,与0异或还是本身num1num2res000011101110...原创 2022-03-05 14:36:07 · 339 阅读 · 0 评论 -
#pragma和ifndef的区别
首先#pragma once是编译器相关的,有的编译器支持,有的编译器不支持1、#ifndef的方式依赖于宏名字不能冲突,所以这可以保证同一个文件不会被包含多次,也能保证多份拷贝的文件不会被同时包含;缺点就是如果不同内容头文件的宏名不小心“撞车”,编译器则只能包含其中一个;2、#pragma once则由编译器提供保证:同一个文件不会被编译多次。注意这里所说的“同一个文件”是指物理上的一个文件;缺点就是,某个头文件有多份拷贝,本方法不能保证他们不被重复包含。3、综上,#ifndef 保证宏名不重复原创 2020-08-25 21:50:49 · 354 阅读 · 0 评论 -
宏函数(宏定义)使用注意
前言 一些经常使用的简单函数,我们会把他定义为宏函数,宏函数确实具有一些优势,本文将讲述宏函数的使用方法和重点踩坑。使用方便提高系统运行效率:宏函数并不是真正的函数,只是把语句嵌在其他函数内,所以宏函数并不需要函数调用。1. 宏函数和内联函数的区别 未了解以前,我感觉这两者似乎没有什么区别,就是书写方式不同而已。但有了了解以后,感觉这两者还是颇有差距的。宏函数在预处理阶段就会展开,而内联函数在编译时才会展开(展现)编译器在处理内联函数会优化,可能不会按我们的需求进行展开.其他比如调原创 2022-02-19 10:44:46 · 7712 阅读 · 0 评论 -
数组循环存储覆盖
结构体赋值#include <stdio.h>#include <string.h>typedef struct{ int num; char name[6]; short height;} STR_STU; int main(){ STR_STU xm = {0}; STR_STU xh = {0}; xm.num = 1000; xm.height = 169; memcpy(xm.name,"ad",4); printf("xm's big n原创 2022-02-09 11:13:48 · 591 阅读 · 0 评论 -
Gtest
一、初始Gtest和框架搭建1.4 Demoint Foo(int a, int b){ if (a == 0 || b == 0) { throw "don't do that"; } int c = a % b; if (c == 0) return b; return Foo(b, c);}#include <gtest/gtest.h>TEST(Foo原创 2022-01-12 13:51:21 · 829 阅读 · 0 评论 -
C/C++Makefile
1. 代码编译基本流程1、预处理宏定义展开、引入头文件、去除注释2、汇编生成汇编代码3、编译生成二进制文件4、链接生成可执行文件gcc -* hello.c -o hello.*-E :预处理生成.i gcc -E hello.c -o hello.i-S :汇编生成.s gcc -S hello.i -o hello.S-c :编译生成.o gcc -c hello.S -c hello.o其中 -o :指定生成文件名gcc hello.o -o hello.e原创 2022-01-04 23:36:16 · 529 阅读 · 0 评论 -
C调用C++和C++调用C
主要介绍C和C++混合编译时,C和C++的函数互相调用的场景时需要注意的地方,包括extern "C"和函数封装等。原创 2021-12-24 13:30:54 · 576 阅读 · 0 评论 -
有关初始化列表和构造函数赋值的区别
如下代码所示,一种是初始化列表,一种是构造函数体内赋值class test{public: test(int y):x(y){} test(int y){x = y;}private: int x;};我们知道这两个最后的效果是一样的,那么区别在哪里呢?过程肯定是不一样的。初始化列表不等同于函数体内赋值,先通过初始化列表给初始值,然后再执行函数体内的操作。如果没有显示指明初始化列表,就会先按照默认值初始化一遍,再执行函数体内的操作。把赋值操作放在函数体内,相当于初始化了一次原创 2020-08-05 20:14:57 · 443 阅读 · 0 评论 -
虚析构函数
1. 前言 首先就是析构函数为什么要声明为虚函数?不声明为虚函数行不行? 答案是不行。析构函数不声明为虚函数会造成内存泄露。来看看为什么。2. 虚析构函数 基类和子类都有可能存在申请堆空间,需要在析构函数中处理释放。 C++的面向对象特性,所以我们经常会使用基类指针指向子类对象。当对象释放时,基类和子类的析构函数同时被调用,不会存在内存泄露。3. 析构函数不是虚函数...原创 2021-11-19 23:04:53 · 64 阅读 · 0 评论 -
C++继承中的构造函数
1. 子类中的构造和析构调用顺序子类对象在构造时首先调用父类的构造函数再调用子类构造函数当父类的构造函数中有参数时,必须在子类的初始化列表中显示调用子类析构时首先调用子类析构,再调用父类析构函数子类的成员变量和父类的成员变量同名时, 子类的同名变量会屏蔽父类的。但在子类中仍可使用父类名: : 使用父类的同名成员#include <iostream>using namespace std;class A{public: int a; A(int a)原创 2021-12-08 22:47:07 · 500 阅读 · 0 评论 -
C++继承类成员访问权限修饰符
1. 前言 C++提供了三个修饰符来限定类成员的被访问权限,分别是public protected private. 通过限定访问权限,可以达到程序编写者想要解决的安全问题和权限问题。这种权限的设置对于安全是非常必要的。2. 不同修饰下的类成员被访问权限public:被public修饰的类成员可以在任何地方被访问到。protected:被protected修饰的类成员可以在类内部,子类内部和友元函数访问到。但不能通过类对象访问。private:被private修饰的类成员可以在类内部和友元函原创 2021-12-07 23:17:36 · 1128 阅读 · 0 评论 -
友元类和友元函数
1. 友元类2. friend友元函数 友元函数不是类的成员函数,函数声明为这个类的友元函数可以访问stu对象的私有成员,拥有访问权限。 当不使用友元函数的时候,这个函数就是成员变量。调用时:使用函数(对象);不是对象.函数;定义时:也不需要Box::函数{ }实例:#include <iostream>using namespace std; class Box{ double width;public: friend void print原创 2021-11-14 22:33:09 · 206 阅读 · 0 评论 -
C++运算符重载
语法:返回值类型 operator 符号(参数列表);实例:#include<iosream>using namespace std;class Context{public:/*------------ 重载'<' ------------*/bool operator <(Context &other){ if(this->val <= other.val) return true; return false;}/*---原创 2021-11-14 22:16:53 · 269 阅读 · 0 评论 -
C++的四种_cast运算符
前言在C语言中,使用强制类型转换进行变量之间的类型转换,主要形式有两种,如下:int a(10);double b=(double)a;double c=double(a);对于进行简单的类型转换,这种方法简单有效,C++也保留了这种强制类型转换,但是这种强制类型转换无法适用于类和类的指针;ANSI-C++标准定义了四个新的转换符:reinterpret_cast, static_cast, dynamic_cast和const_cast,目的在于提供类之间的类型转换;1、reinterpre原创 2020-08-29 20:32:10 · 1146 阅读 · 1 评论 -
C++重载ostream和istream输出自定义对象
class stu{public: int age; int score; string name; stu(int age,int score,string name):age(age),score(score),name(name){} friend ostream& operator << (ostream & os, stu& s){ os << s.age << ' ' <&原创 2020-09-07 20:23:10 · 1200 阅读 · 0 评论 -
拷贝构造函数
拷贝构造函数1. 前言 拷贝构造函数用于使用一个对象初始化另一个对象的时候,系统会默认为我们声明实现一个拷贝构造函数,这种默认的拷贝构造函数为浅拷贝。2. 拷贝构造函数实现在这里插入代码片#ifndef __CONTEXT_H#define __CONTEXT_H#include <vector>class Context{public: Context(); ~Context(); Context (const Context &o原创 2021-11-12 23:39:21 · 979 阅读 · 0 评论 -
extern关键字详细解释
extern 可以置于变量或者函数前,以表示这个变量或函数别的文件中定义,提示编译器在遇到此变量或函数的时候在其他模块寻找其定义。主要使用方式有两种:如果函数的声明中带有extern,说明这个函数定义在其他文件中,这样的好处是可以取代include"**.h",在一些复杂的项目中这样使用比较方便。最好的做法是全部函数声明前添加extern.1 全局变量在.cpp中定义,在.h中extern声明如果没有extern,对于 int a;和int a = 0;,即是定义也是声明但是有了er原创 2021-11-01 19:12:29 · 1666 阅读 · 1 评论 -
STL容器操作集合
0. 公共#include <algorithm>reverse(nums.begin(), nums.end());sort(nums.begin(), nums.end());1. vector#include <vector>vector<int> nums;nums.push_back(5);2. map3. unordered_map4. stack5. queue原创 2021-10-31 20:06:50 · 76 阅读 · 0 评论 -
内存分区-包含bss段data段
都说四大内存分区: 代码区、全局区、堆区、栈区但是这个说法比较粗略。其实从低地址->高地址:依次为代码区,常量,全局变量和静态变量,bss段,堆区、栈区。代码区常量:const、define全局区(data段):静态变量和初始化的全局变量。data段的映像(包含了各个变量的初值)保存在“只读数据段”,这样启动代码就可以简单地复制这个映像到data段,所有的已初始化变量就都初始化了bss段:存储未初始化的全局变量:放在一起是为了简单调用 memset 就可以把所有未初始化的都清0堆区原创 2021-10-22 10:01:09 · 426 阅读 · 0 评论