
001-基础知识
文章平均质量分 66
C/C++基础知识
牛不才
c/c++ linux 后端 架构 搜索引擎
展开
-
C++协程
协程(Coroutine)是程序组件,可以在执行过程中暂停并在稍后继续执行。与传统的子例程(如函数或过程)不同,子例程一旦调用,必须等其返回后才能继续执行调用它的代码。协程则可以在执行过程中暂停,将控制权交还给调用者,并且可以在稍后从暂停的地方继续执行。可以在执行过程中暂停和恢复:这使得协程能够在需要的时候让出控制权,然后在适当的时候恢复执行。保持状态:协程在暂停时会保存其当前的执行状态(包括局部变量和程序计数器),在恢复时可以从上次暂停的地方继续执行。协同调度。原创 2024-06-08 17:41:17 · 1263 阅读 · 2 评论 -
python中的预编译正则表达式
预编译正则表达式指的是使用Python的re模块中的函数提前将正则表达式的字符串形式编译成一个正则表达式对象。这样,当你需要在多个地方或多次使用同一个正则表达式时,你可以重用这个编译后的对象,而不是在每次使用时重新编译表达式。这种做法可以提高效率,特别是在需要频繁使用同一正则表达式进行匹配的场景中。原创 2024-06-01 22:14:47 · 748 阅读 · 0 评论 -
python正则表达式中的分组功能
在Python的re模块中,group()方法是用于从一个匹配的对象(例如,re.match或re.search返回的对象)中提取匹配的字符串。当你使用正则表达式进行匹配时,匹配对象会包含原始字符串中与模式匹配的部分。group()方法可以用来访问这些匹配的部分。group(0)group()group(n)n()n=1n=2如果正则表达式中包含了括号(用于分组),那么你可以通过group(n)来访问每个分组的匹配内容。原创 2024-06-01 22:03:08 · 1063 阅读 · 0 评论 -
python中的正则表达式
Python中的正则表达式(Regular Expressions,简称regex)是一种强大的字符串处理工具,它通过定义搜索模式来匹配、查找、替换或拆分字符串。正则表达式在文本处理、数据清洗和验证等领域非常有用。Python通过内置的re模块提供了对正则表达式的支持。原创 2024-06-01 21:58:21 · 1050 阅读 · 0 评论 -
什么是gRPC?
首先,创建一个Proto文件(calculator.proto),定义服务和消息类型。// 定义请求消息// 定义响应消息// 定义计算器服务。原创 2024-06-01 21:26:09 · 1390 阅读 · 0 评论 -
C++模板元编程--函数萃取
在C++中,是一个非常有用的模板函数,它是标准库头文件的一部分。它的主要作用是在不创建对象的情况下,获取该类型的引用,从而允许在编译时表达式中使用该类型的成员函数或成员变量,即使没有默认构造函数也可以。这在模板编程和类型萃取(type traits)中尤其有用,特别是在编写依赖于SFINAE(Substitution Failure Is Not An Error)的代码时。原创 2024-05-29 06:00:00 · 610 阅读 · 0 评论 -
string_view
是 C++17 引入的一种非拥有型的字符串处理工具,它提供了对字符序列的轻量级、不可修改的视图。与直接使用或字符数组相比,可以提高性能和减少内存使用,因为它不负责管理字符串数据的存储和生命周期,仅仅是提供一种访问已存在字符串数据的方法。原创 2024-05-24 09:12:24 · 347 阅读 · 0 评论 -
std::stringstream的原理和使用时的注意事项
是 C++ 标准库中的一个类,位于头文件中。它提供了一种在内存中操作字符串的方式,类似于文件流的操作。继承自,因此它具有输入流 () 和输出流 () 的功能。原创 2024-05-18 11:10:23 · 384 阅读 · 0 评论 -
std::type_index 用在什么地方
是一个类,它的对象表示类型的标识符。它可以用于在运行时比较两个类型是否相同,或者在容器中存储类型标识符。作为键,以类型名称(字符串)作为值。然后,我们用不同类型的。还可以用于实现一些设计模式,例如访问者模式。和相应的类型名称填充了映射。可以用作在运行时确定应该调用哪个函数的键。在这个例子中,我们首先创建了一个。常用于标识数据类型。运算符获取类型,并将其转换为。,从映射中检索每种类型的名称。中存储每种类型的元数据。原创 2024-05-14 08:28:02 · 473 阅读 · 0 评论 -
闭包是什么?
在需要自定义排序规则时,例如使用std::sort对自定义类型数组或容器排序,lambda表达式允许你以简洁的方式提供比较逻辑。});// 输出: 1 2 3 4 5C++中的闭包(通过lambda表达式)提供了一种强大的方式来编写清晰、灵活且高效的代码。它们的应用场景涵盖了从STL算法的使用到并发编程、事件处理等多个方面,显著提升了C++编程的表达力和实用性。原创 2024-05-10 09:20:46 · 595 阅读 · 0 评论 -
什么是函数式编程?
在函数式编程中,函数是"第一类"实体,意味着它们可以作为参数传递给其他函数,可以作为返回值,也可以被赋值给变量。我们将展示如何使用C++的lambda表达式和标准模板库(STL)中的算法来实现一个函数,该函数接受一个整数列表,并返回一个新列表,其中包含原列表中每个数的平方。在函数式编程中,常常会将小的、专一的函数组合起来,完成更复杂的操作,这样有助于代码的可读性和可维护性。:许多函数式编程语言拥有强大的类型系统,支持类型推断,使得代码更加安全和清晰,同时减少了需要明确声明类型的需求。原创 2024-05-10 09:11:14 · 485 阅读 · 0 评论 -
Boost.Preprocessor库
使用预处理器,开发者可以定义宏,进行条件编译,以及包含其他文件。Boost.Preprocessor库是Boost C++库的一部分,提供了一组扩展的预处理器元编程功能。Boost.Preprocessor库的主要优点是能够在编译阶段生成代码,这可以减少运行时的计算量,提高程序的效率。在这个例子中,BOOST_PP_SEQ_FOR_EACH宏将打印序列(1)(2)(3)(4)(5)中的每个元素。这个例子中,BOOST_PP_TUPLE_ELEM宏将打印元组TUPLE中的第三个元素,也就是3。原创 2024-05-08 00:09:51 · 606 阅读 · 0 评论 -
C++中不要重新定义继承而来的non-virtual函数
这意味着即使通过基类的指针或引用调用该函数,也会调用派生类中的版本,这可能违反了多态性原则,导致无法调用预期的基类函数。:非虚函数不支持运行时多态,这意味着即便派生类中有与基类同名的函数,通过基类指针或引用调用该函数时,总是会调用基类的实现,而不是派生类的实现。:重定义非虚函数可能会导致派生类与基类之间的耦合增强,因为派生类需要知道基类的具体实现细节,并且在派生类中复制这些细节。:如果在派生类中重定义了基类的非虚函数,任何对基类函数的修改都需要在所有派生类中进行检查和相应的修改,这增加了代码的维护难度。原创 2024-05-05 16:32:39 · 554 阅读 · 0 评论 -
std::any简介
这在某些应用程序中可能非常有用,比如插件架构,其中插件可能需要在运行时向宿主应用程序提供不同类型的数据。类的用途在于提供一种方式,用以在同一容器中存储不同类型的对象,并在运行时查询和访问这些对象。是 C++17 标准库中引入的一个类型安全的容器,它可以存储任意类型的单个值。:当你需要在运行时进行动态类型操作时,例如在脚本语言的绑定或动态类型系统中,时,需要注意类型安全的问题,因为尝试提取错误类型的值将抛出。,你可以在一个统一的容器中存储不同类型的配置数据。在这个例子中,我们首先将一个整数存储在。原创 2024-05-05 09:15:45 · 523 阅读 · 0 评论 -
科学的调试方法
这有助于你跟踪你的进展,并且如果你的第一个尝试没有找到问题,这些信息可能会很有用。测试和验证: 一旦你认为找到了问题的解决方案,编写测试来验证你的修复确实解决了问题,并且没有引入新的问题。理解系统:在深入代码之前,充分理解你的系统和软件的架构。查看代码变更: 查看最近的代码变更可能会提供线索,因为新引入的bug通常与最近的变更有关。学习和文档化: 从每次调试经历中学习,并且记录重要的发现以及解决问题的方法,以备将来参考。分析和理论化: 分析问题的症状和你系统的行为。基于你的知识,形成关于导致问题的原因的。原创 2024-05-05 00:49:38 · 192 阅读 · 0 评论 -
不要在栈上分配大数组
但是,这个值是可以配置的。在C++中,如果你在函数中创建一个非常大的数组,它可能会导致栈溢出。这是因为,对于大多数系统,栈的大小是有限的,通常比堆小得多。请注意,尽管可以增加栈的大小,但是栈的空间总是有限的。堆的大小只受到系统可用内存的限制,而栈的大小受到更多的限制。在C++中,栈的大小是由编译器和操作系统决定的,并不是由C++语言本身规定的。所以,尽管可以增加栈的大小,但是最好尽量避免在栈上分配大量的内存。如果你试图在栈上分配一个超出其容量的大数组,可能会导致栈溢出错误,这通常会导致程序崩溃。原创 2023-09-20 09:13:11 · 398 阅读 · 0 评论 -
redis简介(一)
0. redis是什么redis是一个高性能的缓存数据库,支持不限于key-value结构的数据缓存和持久化。直白的讲,可用于进程间通信或者说共享资源,比unix socket、共享内存、消息队列等更方便便捷,而且支持跨语言,凭借着简单实用性能高,被非常广泛应用。Hiredis是Redis数据库的一个简单的C客户端库。它的接口只有简单的几个,但足够大多数场景使用。1. 安装1.1 运行环境和 C语言客户端库这里直接用yum源安装了,这是最简单的方式、yum instal..原创 2021-05-08 22:22:37 · 322 阅读 · 0 评论 -
线程局部存储的三种方式
在某些情况下,我们需要使用线程独有的变量,其他线程不干扰。实现的方式主要有以下三种,一是gcc提供的_thread, 二是pthread提供的pthread_key_t ,三则是c++11提供的thread_local。无论那种方式,它们都能保证变量只对当前线程可见。1. gcc中的_thread_thread 修饰线程周期的变量,主要用法有 __thread int i; extern __thread struct state s; static __t.原创 2021-04-22 21:45:12 · 873 阅读 · 0 评论 -
select和epoll的实现机制
1. TCP三次握手和监听套接字的两个队列1. 未完成队列(SYN_RCVD状态)当第一次握手之后,在未完成队列上建立条目2. 已完成队列(ESTABLISHED状态)三次握手成功之后,该条目转移到已完成队列,accept能够返回。int listen(int sockfd, int backlog);其中backlog这个参数大概为这两个队列总和的最大值,最大值可能是1.5*backlog,这是一个模糊因子。每次握手之间的时间RTT通常为187ms左右。accept由.原创 2021-04-18 23:10:31 · 747 阅读 · 0 评论 -
如何避免和检查C++中的内存错误
内存问题一直是C/C++程序员的心头大患,因为没有GC机制,所以需要我们自己管理内存。在 从“new和malloc的不同”出发看CC++的内存分配 一文中,讲述了几种内存错误的例子,那么避免这些陷阱呢?1. new/delete 、malloc/free、new[]/delete[] 不匹配,导致的内存污染或者内存泄漏2. 野指针,delete/free之后,没有置NULL,再次使用3. delete/free之后,再次释放,double free3. 申请内存之后,没有判断是否成功,直接原创 2021-04-14 20:10:09 · 1091 阅读 · 0 评论 -
C++是怎么实现多态的?
C++是一门面向对象的程序设计语言,其实这句话不严谨。严格来讲C++不仅支持面向对象的编程风格,还支持基于对象、泛型、模板还有函数式的编程风格。通常来讲面向对象是C++中比较常用的一面。1. 什么是多态?面向对象的三大基本特征,封装、继承、多态。多态(polymorphism)指为不同数据类型的实体提供统一的接口,这样做的好处就是我们可以在不修改原有程序的前提下删除或者增加一个新的派生类。有人把多态进行广义的解释,认为多态分两种,一种是静态多态,另一种则是我们要讲的动态多态。静态多态:在编.原创 2021-04-13 20:38:34 · 2406 阅读 · 1 评论 -
操作系统中线程的调度
1. 先到先服务FCFS和去银行办业务一样,大家站队或者取号,先来的先办业务。这是我们能够理解的很朴素的公平主义。对应到代码实现,可以使用有先进先出特性的队列来实现。但对于操作系统而言,有一种情况下这种实现就很差劲。比如,有一个任务A需要执行一个小时,另外N个任务B执行几十秒就能完成。如果任务A先执行,那么N个任务B必须等到A执行完毕之后,才能依次执行。这对于用户来讲,体验显然是非常差的。于是就有了下面的方案。2. 短作业优先SJF短作业优先,可以是平均等待时间最短。用户体验一般和等待时间成正比,越久原创 2021-03-30 22:24:38 · 1135 阅读 · 0 评论 -
https
1. 概述HTTPS还是由HTTP进行通信,不过使用了SSL/TLS 来加密数据。所以它可以提供对网站服务器的身份认证,保护交换数据的隐私与完整性。HTTP默认端口是80端口,HTTPS默认工作的端口是443。工作流程:TCP三次握手建立连接客户端验证服务端数字证书协商对称加密算法,hash算法SSL安全加密隧道协商完成数据使用加密方式参数,用协商好的加密算法和密钥加密,保证数据安全;用hash算法保证数据一致,不被篡改2. HTTP的优缺点:明文传输,安全性差。HTTP响应速度原创 2021-03-25 18:47:23 · 245 阅读 · 0 评论 -
ubuntu18下grpc编译与安装
grpc装起来很麻烦,会有很多坑。按照官方文档或者其他博客的步骤,不注意依赖库的版本页会导致各种问题。0. 环境在 https://grpc.io/docs/ grpc的环境依赖如下LanguageOSCompilers / SDKC/C++Linux, MacGCC 4.9+, Clang 3.4+0.1 操作系统Ubuntu 18.04.4 LTS (腾讯云的虚拟机)坑1:为了支持cpp11,gcc版本要4.9+,所以一些比较老的系统比如centos7.6,gcc原创 2021-03-19 08:08:24 · 2942 阅读 · 5 评论 -
非阻塞connect简介及代码示例
1.概述套接字默认状态是阻塞的,意思就是一旦发起某个套接字调用时,在操作没有完成之前,进程将处于等待睡眠状态。这些套接字调用主要分为四类:输入操作:read、readv、recv、recvfrom和recvmsg输出操作:write、writev、send、sendto和sendmsg接收外部连接:accpet发起外部连接:connectconnect是本文重点要讲述的。建立一个TCP连接,首先要经过三次握手,connect要等到收到发出的SYN对应的ACK才能返回。也就是说建立连接至少要用原创 2021-03-11 20:49:43 · 1001 阅读 · 0 评论 -
unix域协议
1. 概述Unix域协议可以看做是IPC中的一种。它提供两类套接字,字节流套接字(类似TCP),数据报套接字(类似UDP。应用较少)。使用它有以下三大优势:比TCP套接字快出一倍多。可以在不同进程之间传递文件描述符。把用户凭据(用户ID、组ID)提供给服务器,从而进行安全检查。Unix域中用于标识服务器和客户机的协议地址是普通文件的路径名。2. 一个Unix域字节流C/S程序2.1 创建Socket int socket(int domain, int type, int protoc原创 2021-03-09 22:17:33 · 978 阅读 · 0 评论 -
linux 读写锁
概述在某些场景下,读数据操作比写数据操作要频繁,那么可以使用读写锁替代互斥锁来提高应用程序的性能。读写锁的访问规则如下:多个线程共享读操作权限没有读或者写操作时,才可以执行写操作主要操作#include <pthread.h>int pthread_rwclock_rdclock(pthread_rwlock_t *rwptr);//加读出锁,如果读写锁被一个写入者持有则堵塞int pthread_rwclock_wrclock(pthread_rwlock_t *r.原创 2021-02-08 19:06:18 · 243 阅读 · 0 评论 -
[effective c++] 构造析构
条款7, 为多态基类声明virtual析构函数Car *c = new YellowCar();delete c;c指向了一个YellowCar的对象,但c是一个Car指针,如果Car的析构函数不为虚函数,那么delete时,只会调用Car的析构函数。如果YellowCar中有动态申请的内存,这块的释放逻辑通常在它的析构函数来完成,那么delete时,无法调用到YellowCar的析构,所以就造成了内存泄漏。不过要注意,如果没有用到多态,也就是说基类中没有虚函数,而把基类的析构函数声明为虚,这种做翻译 2021-01-20 20:47:18 · 137 阅读 · 0 评论 -
cmake最简用法
安装cmakesudo apt-get install cmake测试源码文件#include<stdio.h>int main(void){ printf("hello world"); return 0;}创建CMakeLists.txtCMAKE_MINIMUM_REQUIRED(VERSION 2.8) #指定最小的版本号...原创 2019-07-21 22:46:16 · 200 阅读 · 0 评论 -
操作系统类型检测宏
#ifdef _WIN32 //define something for Windows (32-bit and 64-bit, this part is common) #ifdef _WIN64 //define something for Windows (64-bit only) #else //define something for Wind...翻译 2019-01-07 14:10:10 · 360 阅读 · 0 评论 -
boost库之program_options
#include <boost/program_options.hpp>#include <iostream>using namespace std;// 解析命令参数bool parseCommandLine(int argc, char* argv[]){ namespace po = boost::program_options; po:...原创 2019-07-31 11:48:54 · 417 阅读 · 0 评论 -
进程控制-创建子进程
如果进程是一辆车,那么至少有启动,运行,停止三种状态。不过,进程和车最大的不同是,进程是可以自我复制的,只要使用函数fork就可以像孙悟空一样再变出一个自己。不过世界上没有两个完全一样的东西,变出来的这个进程,拥有属于自己的ID号(pid),自己的年龄(运行时间)。这些都与父进程不同。通过getpid进程这辆车还可以获取自己的车牌号,getppid可以获取父进程的pid。那么父进程原创 2016-01-11 23:45:17 · 600 阅读 · 0 评论 -
回调函数
回调函数简称回调(是个动词,不是名词,我一开始学的时候纠结了好长时间)。就是用户把一个函数指针作为参数传递给其他函数,后者将“回调”用户的参数。下面是一个简单的例子:verison 0: #include //加 int add(int a,int b){ return a+b;}//减int su原创 2014-02-24 11:11:14 · 646 阅读 · 0 评论 -
C指针的好处
1.参数的传递.当我们想要在子函数中修改传递进去的参数的值(而不是他的拷贝值),在C++中有了引用,但其实引用的本质就是指针.2.动态的内存分配。3.数据结构.数据结构是离不开指针的,无论是链表,树,还是图,都是离不开指针的.利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串。4.并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。转载 2014-02-22 10:30:46 · 1672 阅读 · 0 评论 -
宏定义和括号
为了尽量避免边际效应,宏定义时常要注意括号的使用。例如在编写一个简单的MIN宏时,我们需要加上足够括号才能保证结果尽可能的正确。#define MIN(X,Y) ((X)小提醒:在宏定义中最好全部使用大写字母,以区别正规的代码。但有些情况下,加上括号却是“画蛇添足”的。例如,用预处理指令#define声明一个常数,用以表明1年中有多少秒。#define SE原创 2014-01-05 22:53:18 · 9759 阅读 · 0 评论 -
求结构体元素的偏移量
求结构体元素的偏移量1.使用宏定义2.直接来求原创 2014-01-05 12:36:14 · 5420 阅读 · 0 评论 -
不可小视的位运算
不可小视的位运算原创 2014-01-05 09:17:25 · 1078 阅读 · 2 评论 -
堆(Heap)栈(Stack)
栈和堆区别原创 2013-12-29 10:46:00 · 1049 阅读 · 0 评论 -
预处理器(6)其他预编译指令
1.#error//main.cpp#include#error 数组未分配空间!int main(){ int a[]; return 0;}编译器会生成如下错误信息:main.cpp(4): fatal error C1189: #error : 数组未分配空间!========== 生成: 成功 0 个,失败 1 个,最新 0 个原创 2013-12-28 12:45:49 · 727 阅读 · 0 评论 -
预处理器(5)使用嵌套文件包含
条件编译指令的应用原创 2013-12-28 12:21:49 · 943 阅读 · 0 评论