关于c++:初学小白程序员看过来C面向对象编程知识总归纳

一、比照面向过程具备形象、封装、继承和多态的特:封装是将形象失去的数据和行为相结合,造成了一个有机整体,使得一部分成员充当类与内部的接口,而将其余成员暗藏了起来达到了对成员拜访权限的正当管制,使得不同类之间的影响最小,增强数据安全,简化编程。继承容许在放弃原有类个性的根底上,进行更具体、更具体的阐明,可能很好反映出非凡概念和个别概念之间的关系,是代码复用的根底机制。多态使得一段程序可能具备解决多种类型对象的能力,雷同的音讯在不同的对象下会有不同的动作,加强了编程的灵活性。二、应用const定义常量与用应用define定义常量相比,有什么长处?a. const常量有数据类型,而宏常量没有数据类型。编译器能够对const常量进行类型安全检查,而对宏常量只能字符替换 b. 有些集成化的调试工具能对const常量进行调试,对宏常量不能调试 c.const定义的常量在程序运行的过程中只有一份拷贝,而define定义的常量在内存中有若干拷贝。 三、用代码阐明在规范C++中如何进行输入输出,并解释各语句的含意是什么?cout<<"hello!"<<"world";cin>>a>>b;在输出时,从键盘输入的数据先放在键盘缓冲区中,当按回车键时,键盘缓冲区中的数据输出到程序中的输出缓冲区,造成cin流,而后用流提取运算符“>>”从输出缓冲区中提取数据送给程序中的无关变量。 当用cout和流插入运算符“<<”向显示器输入数据时,先将这些数据送到程序中的输入缓冲区保留,直到缓冲区满了或遇到endl,就将缓冲区中的全副数据送到显示器显示进去。 四、论述C++中函数三种调用的形式实现机制、特点及其实参、形参的格局,最好用代码阐明。(提醒:传址、传值、援用传递)在C++中调用函数时有三种参数传递形式: (1)传值调用; int main( ){ void swap(int,int); //函数申明 int i=3,j=5; swap(i,j); //调用函数swap return 0;} void swap(int a,int b) //希图通过形参a和b的值调换,实现实参i和j的值调换{ int temp; temp=a; //以下3行用来实现a和b的值调换 a=b; b=temp;}(2)传址调用(传指针); 用指针类型作为形参的值调用形式,能够通过参数返回批改后的值。 void main( ){ void swap(int *,int *); int i=3,j=5; swap(&i,&j); //实参是变量的地址} void swap(int *p1,int *p2) //形参是指针变量{ int temp; temp=*p1; //以下3行用来实现i和j的值调换 *p1=*p2; *p2=temp;}如果感觉看完文章有所播种的话,能够关注我一下哦知乎:逆向程序员b站:View程序员每天都会更新咱们的公开课录播以及编程干货和大厂面经也能够间接点击C/C++ linux服务器开发高级架构师来课堂上跟咱们讲师面对面交换须要大厂面经跟学习纲要的小伙伴能够加群1070240985获取 (3)援用传递; 按援用传递,援用实参的援用参数传递给函数,而不是进行参数拷贝。援用类型的形参加相应的实参占用雷同的内存空间,扭转援用类型形参的值,相应实参的值也会随着变动。 int main( ){ void swap(int &,int &); int i=3,j=5; swap(i,j); return 0;} void swap(int &a,int &b) //形参是援用类型{ int temp; temp=a; a=b; b=temp;}五、什么是类的前向申明?应用类的前向申明时,要留神什么?遇到俩个类互相援用的循环依赖状况 ...

November 10, 2020 · 1 min · jiezi

关于c++:聊聊Linux-五种IO模型有图有总结

那么,在正式开始讲Linux IO模型前,比方:同步IO和异步IO,阻塞IO和非阻塞IO别离是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的。所以先限定一下本文的上下文。 1 概念阐明# 在进行解释之前,首先要阐明几个概念: 用户空间和内核空间 过程切换 过程的阻塞 文件描述符 缓存 IO 1.1 用户空间与内核空间## 当初操作系统都是采纳虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操作系统的外围是内核,独立于一般的应用程序,能够拜访受爱护的内存空间,也有拜访底层硬件设施的所有权限。为了保障用户过程不能间接操作内核(kernel),保障内核的平安,操作系统将虚拟空间划分为两局部,一部分为内核空间,一部分为用户空间。针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核应用,称为内核空间,而将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF),供各个过程应用,称为用户空间。 1.2 过程切换## 为了管制过程的执行,内核必须有能力挂起正在CPU上运行的过程,并复原以前挂起的某个过程的执行。这种行为被称为过程切换。因而能够说,任何过程都是在操作系统内核的反对下运行的,是与内核严密相干的。 从一个过程的运行转到另一个过程上运行,这个过程中通过上面这些变动: 保留处理机上下文,包含程序计数器和其余寄存器。更新PCB信息。把过程的PCB移入相应的队列,如就绪、在某事件阻塞等队列。抉择另一个过程执行,并更新其PCB。更新内存治理的数据结构。复原处理机上下文。注:总而言之就是很耗资源,具体的能够参考这篇文章:过程切换。 须要上述材料或者Linux材料的请+qun832218493收费支付! 1.3 过程的阻塞## 正在执行的过程,因为期待的某些事件未产生,如申请系统资源失败、期待某种操作的实现、新数据尚未达到或无新工作做等,则由零碎主动执行阻塞原语(Block),使本人由运行状态变为阻塞状态。可见,过程的阻塞是过程本身的一种被动行为,也因而只有处于运行态的过程(取得CPU),才可能将其转为阻塞状态。当过程进入阻塞状态,是不占用CPU资源的。 1.4 文件描述符fd## 文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的援用的抽象化概念。 文件描述符在模式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个过程所保护的该过程关上文件的记录表。当程序关上一个现有文件或者创立一个新文件时,内核向过程返回一个文件描述符。在程序设计中,一些波及底层的程序编写往往会围绕着文件描述符开展。然而文件描述符这一概念往往只实用于UNIX、Linux这样的操作系统。 1.5 缓存 IO## 缓存 IO 又被称作规范 IO,大多数文件系统的默认 IO 操作都是缓存 IO。在 Linux 的缓存 IO 机制中,操作系统会将 IO 的数据缓存在文件系统的页缓存( page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,而后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。 缓存 IO 的毛病: 数据在传输过程中须要在应用程序地址空间和内核进行屡次数据拷贝操作,这些数据拷贝操作所带来的 CPU 以及内存开销是十分大的。 2 Linux IO模型# 网络IO的实质是socket的读取,socket在linux零碎被形象为流,IO能够了解为对流的操作。方才说了,对于一次IO拜访(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,而后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作产生时,它会经验两个阶段: 第一阶段:期待数据筹备 (Waiting for the data to be ready)。第二阶段:将数据从内核拷贝到过程中 (Copying the data from the kernel to the process)。对于socket流而言, ...

November 10, 2020 · 3 min · jiezi

关于c++:经常被提到的缓存穿透雪崩和击穿到底是什么

对于缓存穿透、缓存雪崩和缓存击穿经常呈现在面试中,明天来看看它到底是何方神圣 redis缓存穿透 了解 重在穿透吧,也就是拜访透过redis间接通过mysql,通常是一个不存在的key,在数据库查问为null。每次申请落在数据库、并且高并发。数据库扛不住会挂掉。解决方案 能够将查到的null设成该key的缓存对象。当然,也能够依据显著谬误的key在逻辑层就就行验证。同时,你也能够剖析用户行为,是否为成心申请或者爬虫、攻击者。针对用户拜访做限度。其余等等,比方用布隆过滤器(超大型hashmap)先过滤。redis缓存雪崩了解 雪崩,就是某货色一拥而上的意思,像雪崩一样。在这里,就是redis缓存个体大规模个体生效,在高并发状况下忽然使得key大规模拜访mysql,使得数据库崩掉。能够设想下国家人口老年化。当前那天人集中在70-80岁,就没人干活了。国家劳动力就造成压力。 解决方案 通常的解决方案是将key的过期工夫前面加上一个随机数,让key平均的生效。思考用队列或者锁让程序执行在压力范畴之内,当然这种计划可能会影响并发量。热点数据能够思考不生效redis缓存击穿了解 缓存击穿,是指一个key十分热点,在不停的扛着大并发,大并发集中对这一个点进行拜访,当这个key在生效的霎时,继续的大并发就穿破缓存,间接申请数据库,如同蛮力击穿一样。 击穿和穿透不同,穿透的意思是想法绕过redis去使得数据库崩掉。而击穿你能够了解为侧面刚击穿,这种通常为大量并发对一个key进行大规模的读写操作。这个key在缓存生效期间大量申请数据库,对数据库造成太大压力使得数据库崩掉。就比方在秒杀场景下10000块钱的mac和100块的mac这个100块的那个订单必定会被抢到爆,一直的申请(当然具体秒杀有本人解决形式这里只是举个例子)。所以缓存击穿就是针对某个罕用key大量申请导致数据库解体。解决方案 能够应用互斥锁防止大量申请同时落到db。布隆过滤器,判断某个容器是否在汇合中能够将缓存设置永不过期(适宜局部状况)做好熔断、降级,避免零碎解体。*本文就到这里了,感觉不错的话无妨点个赞加个关注,省得下次找不到了哦。

November 10, 2020 · 1 min · jiezi

关于c++:C-标准库头文件

C++ 规范库的接口由下列头文件的会集定义。 概念库<concepts> (C++20) 根底库概念 协程库<coroutine> (C++20) 协程反对库 工具库<cstdlib> 通用工具:程序控制、动态内存调配、随机数、排序与搜寻 <csignal> 信号治理的函数与宏常量 <csetjmp> 保留(及跳转)到执行环境的宏(与函数) <cstdarg> 变长实参列表的解决 <typeinfo> 运行时类型信息工具 <typeindex> (C++11) std::type_index <type_traits> (C++11) 编译时类型信息 <bitset> std::bitset 类模板 <functional> 函数对象、函数调用、绑定操作及援用包装 <utility> 多种工具组件 <ctime> C 格调日期/工夫工具 <chrono> (C++11) C++ 工夫工具 <cstddef> 规范宏与 typedef <initializer_list> (C++11) std::initializer_list 类模板 <tuple> (C++11) std::tuple 类模板 <any> (C++17) std::any 类 <optional> (C++17) std::optional 类模板 <variant> (C++17) std::variant 类模板 <compare> (C++20) 三路比拟运算符反对 <version> (C++20) 提供依赖实现的库信息 ...

November 10, 2020 · 3 min · jiezi

关于c++:大专学历的我工作六年了还有机会进大厂吗

输出 [www.baidu.com] 在浏览器的残缺过程,越具体越好。浏览器获取输出的域名 [www.baidu.com]浏览器向域名零碎 DNS 申请解析 [www.baidu.com]的 IP 地址DNS 解析出百度服务器的 IP 地址浏览器与服务器建设 TCP 连贯(默认端口 80)浏览器收回 HTTP 申请,申请百度首页服务器通过 HTTP 申请把首页文件发给浏览器TCP 连贯开释浏览器解析首页文件,展现 web 界面请形容 C/C++程序的内存分区?其实 C 和 C++的内存分区还是有肯定区别的,但此处不作辨别: 1)栈区(stack)— 由编译器主动调配开释 ,寄存函数的参数值,局部变量的值等,其操作形式相似于数据结构中的栈。2)堆区(heap) — 个别由程序员调配开释, 若程序员不开释,程序完结时可能由 OS 回收 ,留神它与数据结构中的堆是两回事,调配形式倒是相似于链表3)全局区(动态区)(static)—,全局变量和动态变量的存储是放在一块的,初始化的全局变量和动态变量在一块区域, 未初始化的全局变量和未初始化的动态变量在相邻的另一块区域。 - 程序完结后由零碎开释。4)、文字常量区 —常量字符串就是放在这里的。 程序完结后由零碎开释。5)、程序代码区—寄存函数体的二进制代码。栈区与堆区的区别: 1)堆和栈中的存储内容:栈存局部变量、函数参数等。堆存储应用 new、malloc 申请的变量等;2)申请形式:栈内存由零碎调配,堆内存由本人申请;3)申请后零碎的响应:栈——只有栈的残余空间大于所申请空间,零碎将为程序提供内存,否则将报异样提醒栈溢出。堆——首先应该晓得操作系统有一个记录闲暇内存地址的链表,当零碎收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,而后将该结点从闲暇结点链表中删除,并将该结点的空间调配给程序;4)申请大小的限度:Windows 下栈的大小个别是 2M,堆的容量较大;5)申请效率的比拟:栈由零碎主动调配,速度较快。堆应用 new、malloc 等调配,较慢;总结:栈区劣势在解决效率,堆区劣势在于灵便; 内存模型:自由区、动态区、动静区;依据 c/c++对象生命周期不同,c/c++的内存模型有三种不同的内存区域,即:自在存依据 c/c++对象生命周期不同,c/c++的内存模型有三种不同的内存区域,即:自在存储区,动静区、动态区。自在存储区:部分非动态变量的存储区域,即平时所说的栈;动静区: 用 new ,malloc 调配的内存,即平时所说的堆;动态区:全局变量,动态变量,字符串常量存在的地位;注:代码尽管占内存,但不属于 c/c++内存模型的一部分;疾速排序的思维、工夫复杂度、实现以及优化办法?疾速排序的三个步骤: (1)抉择基准:在待排序列中,依照某种形式挑出一个元素,作为 "基准"(pivot);(2)宰割操作:以该基准在序列中的理论地位,把序列分成两个子序列。此时,在基准右边的元素都比该基准小,在基准左边的元素都比基准大;(3)递归地对两个序列进行疾速排序,直到序列为空或者只有一个元素。基准的抉择:对于分治算法,当每次划分时,算法若都能分成两个等长的子序列时,那么分治算法效率会达到最大。即:同一数组,工夫复杂度最小的是每次选取的基准都能够将序列分为两个等长的;工夫复杂度最大的是每次抉择的基准都是以后序列的最大或最小元素;快排代码实现:咱们个别抉择序列的第一个作为基数,那么快排代码如下:`void quicksort(vector<int> &v,int left, int right){ if(left < right)//false 则递归完结{ int key=v[left];//基数赋值int low = left; int high = right; while(low < high) //当 low=high 时,示意一轮宰割完结{ while(low < high && v[high] >= key)//v[low]为基数,从后向前与基数比 较{ high--; }swap(v[low],v[high]);while(low < high && v[low] <= key)//v[high]为基数,从前向后与基数比 较{ low++; } swap(v[low],v[high]);} //宰割后,对每一分段反复上述操作quicksort(v,left,low-1); quicksort(v,low+1,right);} }`注:上述数组或序列 v 必须是援用类型的形参,因为后续快排后果须要间接反映在原序列中;优化:上述快排的基数是序列的第一个元素,这样的对于有序序列,快排工夫复杂度会达到最差的 o(n^2)。所以,优化方向就是正当的抉择基数。常见的做法“三数取中”法(序列太短还要联合其余排序法,如插入排序、抉择排序等),如下:①当序列区间长度小于 7 时,采纳插入排序;②当序列区间长度小于 40 时,将区间分成 2 段,失去左端点、右端点和中点,咱们对这三个点取中数作为基数;③当序列区间大于等于 40 时,将区间分成 8 段,失去左三点、中三点和右三点,分别再失去左三点中的中数、中三点中的中数和右三点中的中数,再将失去的三个中数取中数,而后将该值作为基数。具体代码只是在上一份的代码中将“基数赋值”改为①②③对应的代码即可:`int key=v[left];//基数赋值if (right-left+1<=7) {insertion_sort(v,left,right);//插入排序return;}else if(right-left+1<=8){key=SelectPivotOfThree(v,left,right);//三个取中}else{//三组三个取中,再三个取中(应用 4 次 SelectPivotOfThree,此处不具体展现)}须要调用的函数:void insertion_sort(vector<int> &unsorted,int left, int right) //插入排序算法{ for (int i = left+1; i <= right; i++) { if (unsorted[i - 1] > unsorted[i]) { int temp = unsorted[i];int j = i; while (j > left && unsorted[j - 1] > temp){ unsorted[j] = unsorted[j - 1]; j--; } unsorted[j] = temp; } } }int SelectPivotOfThree(vector<int> &arr,int low,int high) //三数取中,同时将中值移到序列第一位{ int mid = low + (high - low)/2;//计算数组两头的元素的下标//应用三数取中法抉择枢轴if (arr[mid] > arr[high])//指标: arr[mid] <= arr[high] { swap(arr[mid],arr[high]);} if (arr[low] > arr[high])//指标: arr[low] <= arr[high] { swap(arr[low],arr[high]);} if (arr[mid] > arr[low]) //指标: arr[low] >= arr[mid] { swap(arr[mid],arr[low]);} //此时,arr[mid] <= arr[low] <= arr[high] return arr[low]; //low 的地位上保留这三个地位两头的值//宰割时能够间接应用 low 地位的元素作为枢轴,而不必扭转宰割函数了}`这里须要留神的有两点:①插入排序算法实现代码;②三数取中函数不仅仅要实现取中,还要将中值移到最低位,从而保障原宰割函数仍然可用。 ...

November 9, 2020 · 2 min · jiezi

关于c++:Linux系统学习系列Linux系统日志管-理下

日志是重要的系统文件,记录和保留了零碎中所有的重要事件。然而日志文件也须要进行定期的保护,因为日志文件是一直增长的,如果齐全不进行日志保护,而任由其随便递增,那么用不了多久,咱们的硬盘就会被写满。 日志保护的最次要的工作就是把旧的日志文件删除,从而腾出空间保留新的日志文件。这项工作如果靠管理员手工来实现,那其实是十分繁缛的,而且也容易遗记。那么 Linux 零碎是否能够主动实现日志的轮替工作呢? logrotate 就是用来进行日志轮替(也叫日志转储)的,也就是把旧的日志文件挪动并改名,同时创立一个新的空日志文件用来记录新日志,当旧日志文件超出保留的范畴时就删除。 须要Linux材料以及Linux入门材料+qun832218493获取 日志文件的命名规定日志轮替最次要的作用就是把旧的日志文件挪动并改名,同时建设新的空日志文件,当旧日志文件超出保留的范畴时就删除。那么,旧的日志文件改名之后,如何命名呢?次要依附 /etc/logrotate.conf 配置文件中的“dateext”参数。 如果配置文件中有“dateext”参数,那么日志会用日期来作为日志文件的后缀,如“secure-20130605”。这样日志文件名不会重叠,也就不须要对日志文件进行改名,只须要保留指定的日志个数,删除多余的日志文件即可。 如果配置文件中没有“dateext”参数,那么日志文件就须要进行改名了。当第一次进行日志轮替时,以后的“secure”日志会主动改名为“secure.1”,而后新建“secure”日志,用来保留新的日志;当第二次进行日志轮替时,“secure.1”会主动改名为“secure.2”,以后的“secure”日志会主动改名为“secure.1”,而后也会新建“secure”日志,用来保留新的日志;以此类推。 logrotate配置文件咱们来查看一下 logrotate 的配置文件 /etc/logrotate.conf 的默认内容。 [root@localhost ~]# vi /etc/logrotate.conf see "man logrotate" for detailsrotate log files weeklyweekly 每周对日志文件进行一次轮替keep 4 weeks worth of backlogs rotate 4保留4个日志文件,也就是说,如果进行了5次日志轮替,就会删除第一个备份曰志create new (empty) log files after rotating old ones create在日志轮替时,主动创立新的日志文件use date as a suffix of the rotated file dateext应用日期作为日志轮替文件的后缀uncomment this if you want your log files compressed #compress日志文件是否压缩。如果勾销正文,则日志会在转储的同时进行压缩以上日志配置为默认配置,如果须要轮替的日志没有设定独立的参数,那么都会遵循以上参数如果轮替曰志配置了独立参数,那么独立参数的优先级更高RPM packages drop log rotation information into this directory include /etc/logrotate.d蕴含/etc/logrotate.d/目录中所有的子配置文件。也就是说,会把这个目录中所有的子配置文件读取进来,进行日志轮替no packages own wtmp and btmp -- we'11 rotate them here以下两个轮替曰志有本人的独立参数,如果和默认的参数抵触,则独立参数失效/var/log/wtmp { ...

November 9, 2020 · 4 min · jiezi

关于c++:菜鸟福音28本书籍循序渐进让你成为大牛附学习大纲一份

很多大三大四的敌人上了几年的课对编程却还是一头雾水,过分点说是无所不知。学了几年除了晓得一些专业名词之外便没有别的播种了,写过我的项目的同学那更是百里挑一,算是同学中顶好学的了。 所以明天我给这部分敌人整顿了一套书籍,一共28本,根底差不要怕,哪怕是没有任何根底,正在自学的敌人也能够看看,这28本书足以让你从一个什么都不懂的菜鸟成为一个敲代码如有神的大牛,须要这些书籍电子档的能够进群973961276获取,或者间接来c/c++ 企业级我的项目实战课堂上参加抽奖获取这些书籍的实体书。 闲话少说,咱们来看看是哪些书。 书籍目录1、C Primer Plus 第6版2、C语言入门经典(第5版)3、图解算法4、数据结构与算法剖析 C语言形容(原书第2版)5、 C语言核心技术(原书第2版)6、C专家编程 7、C 和指针  8、C陷阱与缺点9、C语言深度解剖(第3版) 10、《程序员修炼之道》11、《高质量程序设计指南》12、《C/C++深层摸索》13、《算法导论》14、《计算机程序设计艺术》 作者:Donald E.Knuth15、计算机算法的设计与剖析 作者:Aho,Hopcroft,Ullman16、数据结构(C语言版) 严蔚敏 吴伟民17、C++ Primer (4th Edition) 美)Stanley B.Lippman,Josée LaJoie,Barbara E.Moo18、C++ Primer Plus (美)Stephen Prata19、Essential C++ (美)Stanley B.Lippman20、Effective C++, Third Edition (美)Scott Meyers21、(美)Scott MeyersScott Meyers (美)Scott Meyers22、Thinking in C++ Bruce Eckel 【作者】 Bruce Eckel23、Inside the C++ Object Model (美)Stanley B.Lippman24、The Complete C++ Training Course  (美)Harvey M.Deitel Paul James Deitel **25、C++设计模式——基于Qt 4开源跨平台开发框架 (美)伊斯特(EEzust,A.)26、C++Qt设计模式 [美] 艾朱斯特,[美] 艾朱斯特 著27、Windows程序设计 第6版 /微软技术丛书28、Windows程序设计 第6版 /微软技术丛书 [美] Charles Petzold 著,张大威,汤铭,段洪秀 译29、深入浅出WPF 刘铁猛 著30、Windows 程序设计-第5版CharlesPet**  1、C Primer Plus 第6版 2、 C语言入门经典(第5版) 3、图解算法 4、数据结构与算法剖析 C语言形容(原书第2版) 5、 C语言核心技术(原书第2版) 6、C专家编程  7、C 和指针   8、C陷阱与缺点 9、C语言深度解剖(第3版)  10、《程序员修炼之道》 11、《高质量程序设计指南》 12、《C/C++深层摸索》 13、《算法导论》 14、《计算机程序设计艺术》 作者:Donald E.Knuth 15、计算机算法的设计与剖析 作者:Aho,Hopcroft,Ullman 16、数据结构(C语言版) 严蔚敏 吴伟民  17、C++ Primer (4th Edition) 美)Stanley B.Lippman,Josée LaJoie,Barbara E.Moo 18、C++ Primer Plus (美)Stephen Prata 19、Essential C++ (美)Stanley B.Lippman 20、Effective C++, Third Edition (美)Scott Meyers 21、Thinking in C++ Bruce Eckel  22、Inside the C++ Object Model (美)Stanley B.Lippman 23、The Complete C++ Training Course  (美)Harvey M.Deitel Paul James Deitel 24、C++设计模式——基于Qt 4开源跨平台开发框架 (美)伊斯特(EEzust,A.) 25、C++Qt设计模式 [美] 艾朱斯特,[美] 艾朱斯特 著 26、Windows程序设计 第6版 /微软技术丛书 27、深入浅出WPF 刘铁猛 著 28、Windows 程序设计-第5版CharlesPet 最初针对有些敌人不晓得该如何学习晋升编程的敌人,我在这里也给大家筹备了一份学习纲要,心愿能对自学或自我晋升的敌人有所帮忙。 好了,本文就到这里了,感激大家看到这里,棘手点个赞和关注那是再好不过了。

November 9, 2020 · 1 min · jiezi

关于c++:适合cc新手学习的一些项目别给我错过了

俗话说:万事开头难,学习编程也是,在c/c++我的项目实战群里,常常遇到有小伙伴询问编程语言如何入门方面的问题,如: 我要学习C或者C++语言,有什么开源我的项目能够举荐吗?我是某编程语言的老手,有什么练手的我的项目举荐吗?等等本人在摸索后退的敌人能够进群973961276来一起学习,不足我的项目实战经验的同学能够看这里c/c++  企业级我的项目实战,文末附了一份c/c++入门学习纲要,不过可能有点不清晰,须要清晰版的请评论区留言或者进群获取 See,这就是本系列文章的由来,咱们心愿学习c/c++语言的同学们,读完咱们的入门系列,能够找到学习的方向、零碎的学习语言,而后做个简略的小玩意,不只是 Hello World 。 以下为 C++ 篇 的内容。不论哪门编程语言,根底都是很重要的。所以咱们要先从根本的语法和基础知识学习学起,一步步把握这门语言。 一、根底1.1 一个我的项目入门 C++ 足以:CPlusPlusThingsCPlusPlusThings 是国人开源一个 C++ 学习我的项目。它系统地将 C++ 学习分为了【根底进阶】、【实战系列】、【C++2.0 新个性】、【设计模式】和【STL 源码分析】、【并发编程】、【C++ 习用法】、【学习课程】、【工具】、【拓展】。 作为一个全面零碎的 C++ 学习我的项目,CPlusPlusThings 是优良的,它正当地安顿了 10 Days 的实战局部,在实战中理解语法和函数用法,惟一有余的是,在正文局部有些不尽人意,对局部老手程序员并不是很敌对。【根底进阶】局部内容: const 那些事static 那些事decltype 那些事援用与指针那些事宏那些事GitHub 地址→github.com/Light-City/…1.2 根底局部之算法:C-Plus-PlusC-Plus-Plus 是收录用 C++ 实现的各种算法的汇合,并依照 MIT 许可协定进行受权。这些算法涵盖了计算机科学、数学和统计学、数据迷信、机器学习、工程等各种主题。除外,你可能会发现针对同一指标的多个实现应用不同的算法策略和优化。 GitHub 地址→github.com/TheAlgorith…二、进阶2.1 古代 C++:modern-cpp-tutorialmodern-cpp-tutorial 是古代 C++ 教程,它的目标是提供对于古代 C++(2020 年前)的相干个性的全面介绍。除了介绍了代码之外,它还尽可能简略地介绍了其技术需要的历史背景,这对了解为什么会呈现这些个性提供了很大的帮忙。 GitHub 地址→github.com/changkun/mo… 2.2 进阶指南:CppTemplateTutorialCppTemplateTutorial 为中文的 C++ Template 的教学指南。与出名书籍 C++ Templates 不同,该系列教程将 C++ Templates 作为一门图灵齐备的语言来讲授,以求帮忙读者对 Meta-Programming 死记硬背。本我的项目写作初衷,就是通过 “编程语言” 的视角,介绍一个简略、清晰的 “模板语言”。我会尽可能地将模板的诸多因素连串起来,用一些简略的例子帮忙读者学习这门 “语言”,让读者在编写、浏览模板代码的时候,能像 if(exp) { dosomething(); } 一样的信手拈来,让 “模板元编程” 技术成为读者牢固把握、可触类旁通的有用技能。 ...

November 8, 2020 · 1 min · jiezi

关于c++:你手里都有哪些offer

在这里给大家整顿了腾讯、阿里、百度、华为、头条等一共九家大厂2020年的面试题以及答案,篇幅所限,我就每家的只放两道题了,有须要完整版的敌人能够评论区留言获取。不足我的项目实战经验的小老弟能够点这里☞c/c++企业级我的项目实战。 文末还给大家放了一份学习纲要,如果看完文章能棘手给我点个赞那就再好不过了。 一、腾讯1.删除字符串s1中在字符串s2中呈现的字符。 基本思路:把s1的字符存到一个set外面,而后遍历s2,看是否呈现过,呈现过就erase掉。然而间接输入set的元素这样会扭转程序,要想程序不变,就程序遍历一下s1 看是否呈现,呈现就输入。 #include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#include <set>#include <queue>#include <map>using namespace std;typedef long long LL;const int maxn=1005;set<char>s;int main() {string s1,s2;cin>>s1>>s2;int len=s1.length();for (int i=0;i<len;i++)s.insert(s1[i]);len=s2.length();for (int i=0;i<len;i++){if (s.count(s2[i]))s.erase(s.find(s2[i]));}len=s1.length();for (int i=0;i<len;i++){if (s.count(s1[i]))cout<<s1[i];}cout<<endl;return 0;2. 求一个论坛的在线人数,假如有一个论坛,其注册ID有两亿个,每个ID从登陆到退出会向一个日志文件中记下登陆工夫和退出工夫,要求写一个算法统计一天中论坛的用户在线散布,取样粒度为秒。 答案: 一天总共有3600*24=86400秒。 定义一个长度为86400的整数数组intdelta[86400],每个整数对应这一秒的人数变动值,可能为正也可能为负。开始时将数组元素都初始化为0。 而后顺次读入每个用户的登录工夫和退出工夫,将与登录工夫对应的整数值加1,将与退出工夫对应的整数值减1。 这样解决一遍后数组中存储了每秒中的人数变动状况。 定义另外一个长度为86400的整数数组intonline_num[86400],每个整数对应这一秒的论坛在线人数。 假如一天开始时论坛在线人数为0,则第1秒的人数online_num[0]=delta[0]。第n+1秒的人数online_num[n]=online_num[n-1]+delta[n]。 这样咱们就取得了一天中任意工夫的在线人数。 二、阿里巴巴1、应用mysql索引都有哪些准则?索引什么数据结构? B+tree和B tree什么区别? 答案: 1、    对于查问频率高的字段创立索引; 2、    对排序、分组、联结查问频率高的字段创立索引; 3、    索引的数目不宜太多 起因:a、每创立一个索引都会占用相应的物理控件; b、过多的索引会导致insert, update、delete语句的执行效率升高; 4、    若在理论中,须要将多个列设置索引时,能够采纳多列索引 如:某个表(假如表名为Student),存在多个字段(StudentNo, StudentName, Sex, Address, Phone, BirthDate),其中须要71 StudentNo, StudentName 字段进行查问,对 Sex字段进行分组,对BirthDate字段逹行排序,此时能够创立多列索引index index_najne (StudentNo, StudentName, Sex, BirthDate) ;#index_najne 为索引名 在下面的语句中只创立了一个索引,然而对4个字段都赋予了豪引的性能。 创立多列索引,须要遵循BTree类型,即第一列应用时,才启用索引。 在下面的创立语句中,只有mysql语句在应用到StudentNo字段时,索引才会被启 用。 如: select from Student wheie StudentNo = 1000; #应用到了 StudentNo 字段,索引被启用。 以应用explain检测索引是否被启用如:explain select from Student where StudentNo = 1000; ...

November 7, 2020 · 6 min · jiezi

关于c++:这些程序员学习网站你确定知道一起来看看吧

前言:明天我就来总结一些程序员必备的网站,囊括开源我的项目、解决bug、技术分享、一线资源和自我晋升的网站,心愿能对宽广程序猿有所帮忙,连忙给我珍藏起来,下次刷不到了可别说我没揭示你。 咱们首先来看一下国内比拟风行的程序员社区: 一、知乎:https://www.zhihu.com/people/ni-xiang-cheng-xu-yuan/posts 这个不必多说了吧,知乎是国内最大网络问答社区,连贯各行各业的用户。其中程序员始终占据着半壁江山,老码农们分享着彼此的常识、教训和见解,为中文互联网源源不断地提供多种多样的信息。 二、哔哩哔哩:https://space.bilibili.com/702994697 这个想必也无需赘言,B站前身是二次元文化的小众视频社区,起初发展壮大倒是学习版块倒是占据了不少的底盘,程序员便是其中佼佼者,你说这找谁说理去。 三、CSDN:https://mp.csdn.net/console/home 老牌社区也挺好,就是广告和低质量内容多些,这个根本都是间接搜寻后果跳转,犯懒不想看英文时候的选项。毛病就是泥沙俱下,须要大家的甄别能力。 四、segmentfault:https://segmentfault.com/u/qtchengxuyuan SegmentFault创建于2012年,是中文畛域较大的技术问答交换社区平台,在这里你能够检索,交换和分享任何技术编程相干的问题及常识。产品原型来自于国外程序员问答社区StackOverflow,但其产品状态通过一年多的倒退,曾经有问答、博客、流动等,它还是多个黑客马拉松流动的组织方。 五、腾讯课堂:https://ke.qq.com/course/417774?flowToken=1028592 六、牛客网:https://www.nowcoder.com/profile/767667413 各个公司的面试题和面经分享,找工作前认真刷一刷,肯定会有很大播种!拿到心仪的 offer! 七、掘金:https://juejin.im/user/4256940640968168 掘金是一个帮忙开发者成长的社区,是给开发者用的 Hacker News,给设计师用的 Designer News,和给产品经理用的 Medium。 八、博客园:https://www.cnblogs.com/ 博客园创建于2004年1月,是一个面向开发者的常识分享社区。自创立以来,博客园始终致力并专一于为开发者打造一个污浊的技术交换社区,推动并帮忙开发者通过互联网分享常识,从而让更多开发者从中受害。博客园的使命是帮忙开发者用代码扭转世界。很多晚期的高质量内容都在博客园。 程序员还有一些必备网站: 1. 算法学习 LintCode:https://www.lintcode.com/ 算法学习网站,下来每天刷两道算法题,走遍天下都不怕。 2. 算法学习 LeetCode:https://leetcode.com/ 也是算法题网站,同上。 3. 算法学习 LeetCode 中文站:https://leetcode-cn.com/ 这个是下面算法题网站的中文站点,英文不好的能够刷这个,英文好的举荐去刷英文网站的题目,还能晋升英语能力。 4. Web 开发练习题:https://www.freecodecamp.org/ 这是国外发动的一个 Web 开发学习的网站,从简略到深刻,一步一步带你学习 Web 开发。就像一本练习册,并且当你实现相应的内容后,会失去相应的资格认证。 5. 百度前端技术学院 — 前端开发我的项目库:http://ife.baidu.com 学前端的看这里,百度官网推出的前端开发学习技术学院,题目从简略到艰难,如果你把外面的题都做会了,找个 BAT 的前端工作不成问题的。 其余学习网站:0. 各种编程语言,编程工具,各种轮子的官方网站 要记得,学习一门语言或者一个工具,最优质的学习网站就是他的官方网站,官网文档。 1. 菜鸟教程:http://www.runoob.com/ 菜鸟教程的 Slogan 为:学的不仅是技术,更是幻想! 记住:再牛逼的幻想也抵不住傻逼似的保持!网站包含了HTML、CSS、Javascript、PHP、C、Python等各种根底编程教程。 ...

November 5, 2020 · 1 min · jiezi

关于c++:美国大选背后实时选票服务器方案实现

课题内容:1.  实时服务器计划选型2.  实时服务器性能参数3.  Nginx可不可用呢?工夫:20:00讲师:King老师地址:高级架构师的成长之路

November 5, 2020 · 1 min · jiezi

关于c++:腾讯研发类笔试面试试题及答案C方向

题很多,先上题后上答案,便于大家思考 问题点: 1、C和C++的特点与区别? 2、C++的多态 3、虚函数实现 4、C和C++内存调配问题 5、协程 6、CGI的理解 7、过程间通信形式和线程间通信形式 8、TCP握手与开释 9、http和https的区别? 10、虚拟内存的概念与介绍 11、单链表的反转算法 12、红黑树以及其查找复杂度 13、KPM字符串匹配 14、TCP超时期待、重传以及流量管制 15、数据库引擎 16、数据库索引1、C和C++的特点与区别? 答:(1)C语言特点: 1.作为一种面向过程的结构化语言,易于调试和保护; 2.体现能力和解决能力极强,能够间接拜访内存的物理地址; 3.C语言实现了对硬件的编程操作,也适宜于应用软件的开发; 4.C语言还具备效率高,可移植性强等特点。 (2)C++语言特点: 1.在C语言的根底上进行裁减和欠缺,使C++兼容了C语言的面向过程特点,又成为了一种面向对象的程序设计语言; 2.能够应用抽象数据类型进行基于对象的编程; 3.能够应用多继承、多态进行面向对象的编程; 4.能够担负起以模版为特色的泛型化编程。 C++与C语言的实质差异:在于C++是面向对象的,而C语言是面向过程的。或者说C++是在C语言的根底上减少了面向对象程序设 计的新内容,是对C语言的一次更重要的改革,使得C++成为软件开发的重要工具。 2、C++的多态 答:C++的多态性用一句话概括:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会依据对象的理论类型来 调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。 1):用virtual关键字申明的函数叫做虚函数,虚函数必定是类的成员函数; 2):存在虚函数的类都有一个一维的虚函数表叫做虚表,类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是 和对象对应的; 3):多态性是一个接口多种实现,是面向对象的外围,分为类的多态性和函数的多态性。; 4):多态用虚函数来实现,联合动静绑定.; 5):纯虚函数是虚函数再加上 = 0; 6):抽象类是指包含至多一个纯虚函数的类; 纯虚函数:virtual void fun()=0;即抽象类,必须在子类实现这个函数,即先有名称,没有内容,在派生类实现内容。 3、虚函数实现 答:简略地说,每一个含有虚函数(无论是其自身的,还是继承而来的)的类都至多有一个与之对应的虚函数表,其中寄存着该类 所有的虚函数对应的函数指针。例: 其中: B的虚函数表中寄存着B::foo和B::bar两个函数指针。 D的虚函数表中寄存的既有继承自B的虚函数B::foo,又有重写(override)了基类虚函数B::bar的D::bar,还有新增的虚函数D::quz。 虚函数表结构过程: 从编译器的角度来说,B的虚函数表很好结构,D的虚函数表结构过程绝对简单。上面给出了结构D的虚函数表的一种形式(仅供参考): 虚函数调用过程 ...

November 5, 2020 · 3 min · jiezi

关于c++:328软妹币买了个项目实战包分享给大家看bai看piao

明天给大家分享一下一个敌人买的实战我的项目包,这个敌人呢跟大部分在座的一样,大学时就是天天打游戏泡酒吧,技术那是齐全拉垮,虽说校招前恶补了两个月理论知识,但我的项目实战经验为零啊,这就如同某些人恋爱实践一套一套的,但你要问他谈过几个女朋友,他能跟你急眼,别问,问就是处男。强调一下真的是敌人,不是我[doge]。 这种状况下显然是找不到称心的工作的,没辙啊,我这位敌人又只能恶补我的项目实战,网上找了许久,明天跟我说这个看起来还不错,于是先花328买了一个小我的项目包,咱们来看看这个我的项目有哪些货色。 篇幅所限,只给大家贴出局部源码,感兴趣的敌人能够点赞评论【我的项目实战】或者进群973961276即可取得所有源码跟电子书哦! 我的项目实战相干的视频材料我放在这里了☞c/c++ 我的项目实战,学习办法在这里☞企业级我的项目实战,三个月疾速待业! 一、C和指针材料这个文件夹里次要有一本叫《C和指针》的电子书和一些源码,其余一些系统就不表了,我在上面贴一些电子书的截图和局部源码给大家看看。 《C和指针》☟ 《C和指针源代码及答案》☟rearrang /*** This program reads input lines from the standard input and prints** each input line, followed by just some portions of the lines, to** the standard output.**** The first input is a list of column numbers, which ends with a** negative number. The column numbers are paired and specify** ranges of columns from the input line that are to be printed.** For example, 0 3 10 12 -1 indicates that only columns 0 through 3** and columns 10 through 12 will be printed.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_COLS 20 /* max # of columns to process */#define MAX_INPUT 1000 /* max len of input & output lines */int read_column_numbers( int columns[], int max );void rearrange( char *output, char const *input, int n_columns, int const columns[] );intmain( void ){ int n_columns; /* # of columns to process */ int columns[MAX_COLS]; /* the columns to process */ char input[MAX_INPUT]; /* array for input line */ char output[MAX_INPUT]; /* array for output line */ /* ** Read the list of column numbers */ n_columns = read_column_numbers( columns, MAX_COLS ); /* ** Read, process and print the remaining lines of input. */ while( gets( input ) != NULL ){ printf( "Original input : %sn", input ); rearrange( output, input, n_columns, columns ); printf( "Rearranged line: %sn", output ); } return EXIT_SUCCESS;}/*** Read the list of column numbers, ignoring any beyond the specified** maximum.*/intread_column_numbers( int columns[], int max ){ int num = 0; int ch; /* ** Get the numbers, stopping at eof or when a number is < 0. */ while( num < max && scanf( "%d", &columns[num] ) == 1 && columns[num] >= 0 ) num += 1; /* ** Make sure we have an even number of inputs, as they are ** supposed to be paired. */ if( num % 2 != 0 ){ puts( "Last column number is not paired." ); exit( EXIT_FAILURE ); } /* ** Discard the rest of the line that contained the final ** number. */ while( (ch = getchar()) != EOF && ch != 'n' ) ; return num;}/*** Process a line of input by concatenating the characters from** the indicated columns. The output line is then NUL terminated.*/voidrearrange( char *output, char const *input, int n_columns, int const columns[] ){ int col; /* subscript for columns array */ int output_col; /* output column counter */ int len; /* length of input line */ len = strlen( input ); output_col = 0; /* ** Process each pair of column numbers. */ for( col = 0; col < n_columns; col += 2 ){ int nchars = columns[col + 1] - columns[col] + 1; /* ** If the input line isn't this long or the output ** array is full, we're done. */ if( columns[col] >= len || output_col == MAX_INPUT - 1 ) break; /* ** If there isn't room in the output array, only copy ** what will fit. */ if( output_col + nchars > MAX_INPUT - 1 ) nchars = MAX_INPUT - output_col - 1; /* ** Copy the relevant data. */ strncpy( output + output_col, input + columns[col], nchars ); output_col += nchars; } output[output_col] = '0';} ...

November 5, 2020 · 5 min · jiezi

关于c++:C和C程序员快要被市场淘汰了

编程语言在某种程度上很像朝代,随着工夫流逝而一代代更迭,有些编程语言正面临着淘汰,沦亡在历史的洪流中。 在互联网上,对于C++将要被市场所淘汰的探讨从未进行过,有人说C++是一门过期的编程语言,也有人说,C++是不可代替的。那么,C++过期了吗?C++程序员会不会被淘汰? 100offer的观点是:企业对C++的需要势必越来越少,C++程序员整体竞争力也将越来越弱,但C++在很长一段时间都不会彻底沦亡。 让咱们先来看一组TIOBE的最新数据。 编程语言排行榜 TOP18 榜单以上是TIOBE于2016年8月公布的「编程语言排行榜 TOP 18榜单」,依据最新排名,Java再度夺得排行榜冠军,有19.010%用户,对应了100offer在7月6日公布的一文《为何优良的Java程序员如此难招?》中的观点—— 从市场上的招聘现状看,Java工程师仍然有着其余语言不可取代的竞争劣势。 C和C++尽管别离拿到了亚军与季军,然而均再次跌破历史最低点,C较上个月降落3.43%,C++较上个月降落1.94%,状况不容乐观。 前 10 名编程语言长期走势图从TIOBE在8月公布的「前 10 名编程语言长期走势图」可能看进去,C++在21世纪初有着不可动摇的位置,从2004年之后,C++的占比开始一直上涨,比照排在前面的编程语言不再具备劣势。 100offer也抉择了五门编程语言,从企业收回面邀数和最终入职数做出比照剖析—— 从企业发给候选人的总面邀占比以及程序员最终入职占比能够看出,java仍是市场上最供不应求的岗位,PHP紧随其后,C++取得的面邀数和offer数没有任何劣势。 已经是编程语言「三巨头」之一的C++,为何现如今会面临如此难堪的场面? 须要C++Linux材料的请+qun832218493收费支付! C++一直消退的起因 1 技术不断更新 以前,绝大数需要都要用C++来写,所以C++曾无比昌盛。现在,很多畛域都开始有专属它的一门语言,使得实现需求变得更为便捷。 家喻户晓,在20世纪末21世纪初,大部分的集体计算机只有文字排版、图像制作的需要,随着集体计算机的迅速遍及,用户基数一直减少,这类需要迅速升高,新增用户们的需要开始转变为信息整合共享。 随着互联网的倒退,技术不断更新,用户只需简略的「傻瓜式」操作就能满足他们的需要,100offer的候选人柯学生举了在app里加地图的例子—— 「以前,这类需要没那么容易,要用到 OS 的 UI 性能去集成一个 native 模块能力实现,当初简略多了,用 Google Maps 做网页的 marshup 就行了。C++在面临新技术时,太多功能有局限性,未免显得简单了,例如,C++的动态类型限度太强导致动静性能有余。」 2 C++已过巅峰期 尽管C++仍在不断更新,但应用C++的员工平均年龄一直增长,能应用C++新我的项目也越来越少,导致C++已过巅峰期。 候选人张学生提出,「C++的语言机制在理论应用有很多问题,导致细节不能使用。举个典型问题,如STL,容易生成错误信息,而Java则不会呈现这类问题。所以,很让人丧气,C++早已过了巅峰期。」 此次承受100offer采访的C++程序员们,有70%示意:在初学时,消耗了太多太多精力投入到语言细节中去了。他们现在在思考:这些细节对除C++以外的利用开发到底有没有作用?或者说,作用只是微不足道? C++还有很强的生命力,只是颠峰早已不在,并且,弱小生命力仅是从历史上的昌盛继承而来。无奈拆穿的事实是:C++在应用领域开始展现出疲态。 3 市场需求缩小 C++一直消退的最重要起因是:市场需求缩小。 从文章结尾提供的相干数据可知:须要C++的企业越来越少,这是不争的事实。 编程语言的盛衰与市场需求的关系更为显著,并非是编程语言自身的优劣所影响市场需求。咱们不得不抵赖的事实是:会大规模自建基础设施的企业,除了BAT等巨头企业外并不多,时代早已悄悄产生扭转。 即使是新兴的互联网巨头企业们,留给基础设施工程师的职位也不会很多,更别提守业公司了。显然易见,C++更偏差于基础设施方向,随着业务零碎开发的门槛持续性升高,C++职位需要势必将越来越低。 当C++只剩下大型企业才有大量需要时,当C++对员工要求也越来越刻薄时,当C++程序员的集体倒退变得更为艰巨时,这门语言天然不可避免会走向消退。 C++为什么不会沦亡 即使C++的市场需求越来越少,但C++是不会沦亡的。从世界范畴的统计数据来看,C++尽管在一直消退,但仍多年排在第三名。所以,在很长一段时间,C++都不会跌出前三的宝座。 C++为什么不会沦亡?100offer采访了多名C++程序员后,得出以下三个观点—— 1.在游戏和工具畛域依然是支流 首先是游戏畛域,Milo Yip示意—— 程序员必须应用C++框架/库,如大部分游戏引擎(如Unreal/Source)及中间件(如Havok/FMOD),尽管有些C++库提供其余语言的绑定,但通常原生的API性能最好、最新。 其次是工具畛域,无论是网络安全还是杀毒软件,C++仍是支流语言。 2.C++程序员的支出没有受到影响 依据100offer的后盾数据显示,目前通过100offer入职的程序员年薪最高达47万,最低22.4万,C++程序员的支出与其它编程语言的岗位相比处于持平状态,没有呈现劣势。 随着C++逐步成为某些特定企业和特定我的项目所需的语言后,高级C++程序员的支出也会更具备竞争性。 ...

November 5, 2020 · 1 min · jiezi

关于c++:适合-C-新手学习的开源项目在-GitHub-学编程

作者:HelloGitHub-小鱼干 俗话说:万事开头难,学习编程也是一样。在 HelloGitHub 的群里,常常遇到有小伙伴询问编程语言如何入门方面的问题,如: 我要学习某一门编程语言,有什么开源我的项目能够举荐吗?我是某编程语言的老手,有什么练手的我的项目举荐吗?等等See,这就是本系列文章的由来,咱们心愿学习各类编程语言的同学们,读(Mark)完咱们的入门系列,能够找到学习的方向、零碎的学习某一门语言,而后做个简略的小玩意,不只是 Hello World 。 《GitHub 上适宜编程入门的我的项目》系列,共计 5 篇文章: C++ 篇Python 篇Go 篇Java 篇JavaScript 篇以下为 C++ 篇 的内容。不论哪门编程语言,根底都是很重要的。所以咱们要先从根本的语法和基础知识学习学起,一步步把握这门语言。 一、根底1.1 一个我的项目入门 C++ 足以:CPlusPlusThingsCPlusPlusThings 是国人开源一个 C++ 学习我的项目。它系统地将 C++ 学习分为了【根底进阶】、【实战系列】、【C++2.0 新个性】、【设计模式】和【STL 源码分析】、【并发编程】、【C++ 习用法】、【学习课程】、【工具】、【拓展】。 作为一个全面零碎的 C++ 学习我的项目,CPlusPlusThings 是优良的,它正当地安顿了 10 Days 的实战局部,在实战中理解语法和函数用法,惟一有余的是,在正文局部有些不尽人意,对局部老手程序员并不是很敌对。【根底进阶】局部内容: const 那些事static 那些事decltype 那些事援用与指针那些事宏那些事GitHub 地址→https://github.com/Light-City/CPlusPlusThings1.2 根底局部之算法:C-Plus-PlusC-Plus-Plus 是收录用 C++ 实现的各种算法的汇合,并依照 MIT 许可协定进行受权。这些算法涵盖了计算机科学、数学和统计学、数据迷信、机器学习、工程等各种主题。除外,你可能会发现针对同一指标的多个实现应用不同的算法策略和优化。 GitHub 地址→https://github.com/TheAlgorithms/C-Plus-Plus二、进阶2.1 古代 C++:modern-cpp-tutorialmodern-cpp-tutorial 是古代 C++ 教程,它的目标是提供对于古代 C++(2020 年前)的相干个性的全面介绍。除了介绍了代码之外,它还尽可能简略地介绍了其技术需要的历史背景,这对了解为什么会呈现这些个性提供了很大的帮忙。 GitHub 地址→https://github.com/changkun/modern-cpp-tutorial 2.2 进阶指南:CppTemplateTutorialCppTemplateTutorial 为中文的 C++ Template 的教学指南。与出名书籍 C++ Templates 不同,该系列教程将 C++ Templates 作为一门图灵齐备的语言来讲授,以求帮忙读者对 Meta-Programming 死记硬背。本我的项目写作初衷,就是通过 “编程语言” 的视角,介绍一个简略、清晰的 “模板语言”。我会尽可能地将模板的诸多因素连串起来,用一些简略的例子帮忙读者学习这门 “语言”,让读者在编写、浏览模板代码的时候,能像 if(exp) { dosomething(); } 一样的信手拈来,让 “模板元编程” 技术成为读者牢固把握、可触类旁通的有用技能。 ...

November 5, 2020 · 1 min · jiezi

关于c++:c-使用-rapidjson-生成-json-并解析

概述应用 rapidjson 生成 json 并对其进行解析。 罕用函数AddMember性能:往对象中增加一个键值对。函数原型GenericValue& rapidjson::GenericValue< Encoding, Allocator >::AddMember( GenericValue< Encoding, Allocator > & name, GenericValue< Encoding, Allocator > & value, Allocator & allocator ) 函数参数 name 是键的名称value 是对应键的值allocator 用来分配内存的分配器,必须与后面应用的雷同。SetString性能:将此值设置为字符串,且复制原字符串。函数原型GenericValue& rapidjson::GenericValue< Encoding, Allocator >::SetString(const Ch * s,SizeType length,Allocator & allocator ) 函数参数 s 是原字符串length 是原字符串的长度,包含前面的空字符allocator 分配器代码#include <iostream>#include <string>#include <fstream>#include <windows.h>#include "rapidjson/prettywriter.h"#include "rapidjson/document.h"#include "rapidjson/istreamwrapper.h"using namespace std;using namespace rapidjson;//-----------------------------------------------------------------------------void AddBasicType(Document &d, Document::AllocatorType & allocator){ d.AddMember("digit", 3, allocator); // 增加整型数据 d.AddMember("height", 170.5, allocator); // 增加浮点类型 d.AddMember("subject1", "math", allocator); // 增加字符串类型,常量形式 string strSubject = "English"; Value valueSubject(kStringType); valueSubject.SetString(strSubject.c_str(), strSubject.size(), allocator); if (!valueSubject.IsNull()) { d.AddMember("subject2", valueSubject, allocator); // 增加字符串类型,变量形式,不能间接对变量进行增加,类型不对 }}//-----------------------------------------------------------------------------void AddObjectType(Document &d, Document::AllocatorType & allocator){ Value valueObject(kObjectType); valueObject.AddMember("sex", "male", allocator); valueObject.AddMember("weight", 95, allocator); d.AddMember("info", valueObject, allocator);}//-----------------------------------------------------------------------------void AddStringArrayType(Document &d, Document::AllocatorType & allocator){ Value valueStr(kStringType); // 单个字符串 Value valueStrArray(kArrayType); // 字符串数组 string strExtraSubject1 = "计算机"; string strExtraSubject2 = "音乐"; string strExtraSubject3 = "体育"; valueStr.SetString(strExtraSubject1.c_str(), strExtraSubject1.size(), allocator); valueStrArray.PushBack(valueStr, allocator); valueStr.SetString(strExtraSubject2.c_str(), strExtraSubject2.size(), allocator); valueStrArray.PushBack(valueStr, allocator); valueStr.SetString(strExtraSubject3.c_str(), strExtraSubject3.size(), allocator); valueStrArray.PushBack(valueStr, allocator); d.AddMember("extraSubject", valueStrArray, allocator);}//-----------------------------------------------------------------------------void AddObjectArrayType(Document &d, Document::AllocatorType & allocator){ Value valueObjectArray(kArrayType); for (int i = 0; i < 3; i++) { Value valueSingleObject(kObjectType); valueSingleObject.AddMember("score", i * 40, allocator); if (i == 0) { valueSingleObject.AddMember("difficulty", "hard", allocator); } else if (i == 1) { valueSingleObject.AddMember("difficulty", "abnormal", allocator); } else { valueSingleObject.AddMember("difficulty", "easy", allocator); } valueObjectArray.PushBack(valueSingleObject, allocator); } d.AddMember("subjectInfo", valueObjectArray, allocator);}//-----------------------------------------------------------------------------void ParseBasicType(Document &d, string jsonData){ if (!d.Parse(jsonData.data()).HasParseError()) { // 解析整型 if (d.HasMember("digit") && d["digit"].IsInt()) { cout << "digit = " << d["digit"].GetInt() << endl; } // 解析浮点型 if (d.HasMember("height") && d["height"].IsDouble()) { cout << "height = " << d["height"].GetDouble() << endl; } // 解析字符串类型 if (d.HasMember("subject1") && d["subject1"].IsString()) { cout << "subject1 = " << d["subject1"].GetString() << endl; } if (d.HasMember("subject2") && d["subject1"].IsString()) { cout << "subject2 = " << d["subject2"].GetString() << endl; } }}//-----------------------------------------------------------------------------void ParseObjectType(Document &d, string jsonData){ if (d.HasMember("info") && d["info"].IsObject()) { const Value& resInfo = d["info"]; // 获取对象 if (resInfo.HasMember("sex") && resInfo["sex"].IsString()) { cout << "resInfo.sex = " << resInfo["sex"].GetString() << endl; } if (resInfo.HasMember("weight") && resInfo["weight"].IsInt()) { cout << "resInfo.weight = " << resInfo["weight"].GetInt() << endl; } }}//-----------------------------------------------------------------------------void ParseStringArrayType(Document &d, string jsonData){ if (d.HasMember("extraSubject") && d["extraSubject"].IsArray()) { const Value& valueStrArray = d["extraSubject"]; size_t len = valueStrArray.Size(); // 获取数组长度 for (size_t i = 0; i < len; i++) { cout << "extraSubject[" << i << "] = " << valueStrArray[i].GetString() << endl; } }}//-----------------------------------------------------------------------------void ParseObjectArrayType(Document &d, string jsonData){ if (d.HasMember("subjectInfo") && d["subjectInfo"].IsArray()) { const Value& valueObjectArray = d["subjectInfo"]; // 获取对象数组 size_t len = valueObjectArray.Size(); for (size_t i = 0; i < len; i++) { const Value& object = valueObjectArray[i]; // 每一个元素都是一个对象 if (object.IsObject()) { cout << "subjectInfo[" << i << "]: "; if (object.HasMember("score") && object["score"].IsInt()) { cout << "score = " << object["score"].GetInt(); } if (object.HasMember("difficulty") && object["difficulty"].IsString()) { cout << " difficulty = " << object["difficulty"].GetString(); } } cout << endl; } }}//-----------------------------------------------------------------------------int main(){ Document d; d.SetObject(); wstring wsValue; Document::AllocatorType &allocator = d.GetAllocator(); // 获取分配器 AddBasicType(d, allocator); // 增加根本类型 AddObjectType(d, allocator); // 增加对象类型,对象中有根本数据类型 AddStringArrayType(d, allocator); // 增加字符串数组类型,数组中的每一个元素是一个字符串 AddObjectArrayType(d, allocator); // 增加对象数组类型,数组中的每一个元素是一个对象 // StringBuffer是一个简略的输入流。它调配一个内存缓冲区,供写入整个JSON。 // 可应用GetString()来获取该缓冲区。 StringBuffer strBuf; Writer<StringBuffer> writer(strBuf); d.Accept(writer); string jsonData = strBuf.GetString(); cout << jsonData << endl << endl; ParseBasicType(d, jsonData); // 解析根本类型 ParseObjectType(d, jsonData); // 解析对象类型 ParseStringArrayType(d, jsonData); // 解析字符串数组类型 ParseObjectArrayType(d, jsonData); // 解析对象数组类型}生成的 json 数据{ "digit": 3, "height": 170.5, "subject1": "math", "subject2": "English", "info": { "sex": "male", "weight": 95 }, "extraSubject": [ "计算机", "音乐", "体育" ], "subjectInfo": [ { "score": 0, "difficulty": "hard" }, { "score": 40, "difficulty": "abnormal" }, { "score": 80, "difficulty": "easy" } ]}参考资料RapidJSON 文档rapidjson库的根本应用

November 4, 2020 · 3 min · jiezi

关于c++:Linux系统学习系列Linux系统日志管-理上

Linux rsyslogd服务及启动办法(详解版)在 CentOS 6.x 中,日志服务曾经由 rsyslogd 取代了原先的 syslogd。Red Hat 公司认为 syslogd 曾经不能满足工作中的需要,rsyslogd 相比 syslogd 具备一些新的特点: 基于TCP网络协议传输日志信息。更平安的网络传输方式。有日志信息的即时剖析框架。后盾数据库。在配置文件中能够写简略的逻辑判断。与syslog配置文件相兼容。rsyslogd 日志服务更加先进,性能更多。然而,不论是该服务的应用,还是日志文件的格局,其实都是和 syslogd 服务相兼容的,所以学习起来根本和 syslogd 服务统一。 咱们如何晓得 Linux 中的 rsyslogd 服务是否启动了呢?如何查问 rsyslogd 服务的自启动状态呢?命令如下: [root@localhost ~]# ps aux | grep "rsyslog" | grep -v "grep"root 1139 0.0 0.2 35948 1500 ? Sl 09:40 0:00 /sbin/rsyslogd -i/var/run/syslogd.pid -c 5#有rsyslogd服务的过程,所以这个服务曾经启动了[root@localhost ~]# chkconfig --list | grep rsyslogrsyslog 0:敞开 1:敞开 2:启用 3:启用 4:启用 5:启用 6:敞开#rsyslog服务在2、3、4、5运行级别上是开机自启动的 零碎中的绝大多数日志文件是由 rsyslogd 服务来对立治理的,只有各个过程将信息给予这个服务,它就会主动地把日志依照特定的格局记录到不同的日志文件中。也就是说,采纳 rsyslogd 服务治理的日志文件,它们的格局应该是对立的。 ...

November 4, 2020 · 4 min · jiezi

关于c++:CC永不过时的语言-数据结构完整版通俗易懂

一、什么是数据结构 数据结构,直白地了解,就是钻研数据的存储形式。 咱们晓得,数据存储只有一个目标,即为了不便前期对数据的再利用,就如同咱们应用数组存储{1,2,3,4,5} 是为了前期获得它们的加和值,无缘由的数据存储行为是对存储空间的不负责任。 因而,数据在计算机存储空间的寄存,决不是胡乱的,这就要求咱们抉择一种好的形式来存储数据,而这也是数据结构的核心内容。 例如,始终以来大家面对的数据存储,都是相似存储 1、2、{a,b,c}、"http://data.biancheng.net" 这样的问题,解决形式无疑是用变量或者数组对数据进行存储,即: int a=1;int b=2;char str[3]={'a','b','c'};char *data="http://data.biancheng.net";然而,如果要存储这样一组数据:{张亮,张平,张华,张群,张晶,张磊},数据之间具备这样的关系:张亮是张平、张华和张群的父亲,同时张平还是张晶和张磊的父亲,数据之间的关系如图 1 所示: 图 1 数据及数据之间的关系 对于存储之间具备简单关系的数据,如果还是用变量或数组来存储(比方用数组存储 {“张亮”,"张平",“张华”,"张群","张晶","张磊"} ),数据存储是没有问题,然而无奈体现数据之间的逻辑关系,前期根本无法应用,显然不明智。 针对此类数据,数据结构中提供有专门的树结构来存储这类数据。再比方,导航无疑是出游旅行的必备神器,在咱们程序员眼中,无论是哪款导航软件,其导航性能的实现都须要大量地图数据的反对。很显著,这些数据绝不是应用变量或数组进行存储的,那样对于数据的应用几乎是个喜剧。 针对此类数据,数据结构提供了图存储构造,专门用于存储这类数据。通过以上两个示例能够体会出,数据结构教会咱们的绝不仅仅是如何存储 1、2、{a,b,c} 这样简略的数据,而是解决具备简单关系的大量数据的存储问题。 因而,数据结构是什么?我认为,数据结构是一门学科,它教会咱们“如何存储具备简单关系的数据更有助于前期对数据的再利用”。 二、数据结构到底学什么数据结构大抵蕴含以下几种存储构造: 线性表,还可细分为程序表、链表、栈和队列;树结构,包含一般树,二叉树,线索二叉树等;图存储构造;上面对各种数据结构做具体解说: (1)线性表 线性表构造存储的数据往往是能够顺次排列的,就像小朋友手拉手,每位学生的后面和前面都仅有一个小朋友和他拉手,具备这种“一对一”关系的数据就能够应用线性表来存储。 例如,存储相似 {1,3,5,7,9} 这样的数据时,各元素顺次排列,每个元素的后面和后边有且仅有一个元素与之相邻(除首元素和尾元素),因而能够应用线性表存储。 线性表并不是一种具体的存储构造,它蕴含顺序存储构造和链式存储构造,是程序表和链表的统称。 (2)程序表程序表,简略地了解,就是罕用的数组,只是换了个名字而已,例如应用程序表存储 {1,3,5,7,9},如图 2 所示: 图 2 程序表构造 因为程序表构造的底层实现借助的就是数组,因而对于初学者来说,能够把程序表齐全等价为数组,但实则不是这样。数据结构是钻研数据存储形式的一门学科,它囊括的都是各种存储构造,而数组只是各种编程语言中的根本数据类型,并不属于数据结构的领域。(3)链表 咱们晓得,应用程序表(底层实现靠数组)时,须要提前申请肯定大小的存储空间,这块存储空间的物理地址是间断的,如图 2 所示。 链表则齐全不同,应用链表存储数据时,是随用随申请,因而数据的存储地位是互相拆散的,换句话说,数据的存储地位是随机的。 为了给各个数据块建设“顺次排列”的关系,链表给各数据块增设一个指针,每个数据块的指针都指向下一个数据块(最初一个数据块的指针指向 NULL),就如同一个个小学生都伸手去拉住下一个小学生的手,这样,看似毫无关系的数据块就建设了“顺次排列”的关系,也就造成了链表,如图 3所示: 图 3 链表构造 (4)栈和队列栈和队列隶属于线性表,是非凡的线性表,因为它们对线性表中元素的进出做了明确的要求。 栈中的元素只能从线性表的一端进出(另一端封死),且要遵循“先入后出”的准则,即先进栈的元素后出栈。 图 4 栈构造示意图 栈构造如图 4所示,像一个木桶,栈中含有 3 个元素,别离是 A、B 和 C,从在栈中的状态能够看出 A 最先进的栈,而后 B 进栈,最初 C 进栈。依据“先进后出”的准则,3 个元素出栈的程序应该是:C 最先出栈,而后 B 出栈,最初才是 A 出栈。 ...

November 4, 2020 · 1 min · jiezi

关于c++:还在看源码自己不写项目永远都是菜鸟

尽管秋招曾经完结了,但不晓得明年春招大伙筹备的怎么样呢?很多小伙伴陷入了一个误区,感觉始终找最难的源码和最生僻的技术看懂了本人的技术就晋升了。 然而面试的时候一问本人写过哪些项目的时候,便坐立不安,因为确实没有做过,毫无教训。那公司为什么要花更多的人力老本来给你兜底练习呢,找一个有实操教训的工程师无论从哪个角度上来说都更划得来,而且写我的项目的过程中自身也能够查漏补缺,是晋升技术最快的办法,编程技术永远不是看会的,你不入手,你永远是个菜鸟。 当然了,有些敌人会说本人想写我的项目,但始终苦于没有学习路径,不晓得如何下手,没有人带着写,呐,当初机会来了,从业开发十多年的Vico老师带你手把手写我的项目,不论是待业还是考研,本人有拿得出手的我的项目无疑都会超级加分,有趣味的敌人能够来看看了,尤其是大三大四的,快给我进来学!!!详情可进群征询!!! 学习直通车:c/c++ 我的项目实战训练待业学习

November 4, 2020 · 1 min · jiezi

关于c++:腾讯T9级别的技术顾问是怎么炼成的

明天给大家分享一下腾讯T9级别的技术顾问的学习路线,心愿对在自学晋升的敌人有一些帮忙,学习路径总结在上面这张思维导图外面了,感觉还不错的请点赞珍藏反对一下、尺寸所限略显含糊,有须要的敌人能够进群获取。 思维导图☟ 一、精进基石 1、数据算法与构造1.1 排序(11种)与KMP 1.2 红黑树证实 1.3 B树与B+树 1.4 Hash与布隆过滤器 2、设计模式(23种)2.1 责任链模式 2.2 过滤器墨海 2.3 公布订阅模式 2.4 工厂模式 3、工程治理3.1 Makefile/cmake/configure 3.2 git /svn与继续集成 3.3 Linux零碎运行时命令 二、高性能网络设计 1、代码实现1.1 网络io与select/poll/epoll 1.2 reactor的原理与实现 1.3 http/https web服务器的实现 1.4 websocket协定与服务器实现 2、计划剖析2.1 服务器百万并发的实现(c10K,c1000k, C10M) 2.2 redis/memcached/Nginx网络组件 2.3 Posix API与网络协议栈 2.4 UDP牢靠协定 QUIC/KCP 三、根底组件实现 1、池式构造1.1 手写线程池 1.2 内存池 ringbuffer 1.3 异步申请池 性能优化,异步mysql 异步dns 异步redis 1.4 mysql连接池 1.5 redis连接池 2、高性能组件2.1 原子操作 CAS 2.2 音讯队列与无锁队列 2.3 定时器的计划 红黑树 工夫轮 最小堆 2.4 锁的实现原理 互斥锁,自旋锁 ,乐观锁,乐观锁,分布式锁 2.5 服务器连贯保活 keepalived 2.6 try/catch的实现 ...

November 4, 2020 · 2 min · jiezi

关于c++:腾讯T9级别技术专家是怎么炼成的

明天给大家分享一下腾讯T9级别的技术顾问的学习路线,心愿对在自学晋升的敌人有一些帮忙,学习路径总结在上面这张思维导图外面了,感觉还不错的请点赞珍藏反对一下、尺寸所限略显含糊,有须要的敌人能够进群获取。 思维导图☟ 一、精进基石 1、数据算法与构造**1.1 排序(11种)与KMP 1.2 红黑树证实 1.3 B树与B+树 1.4 Hash与布隆过滤器** 2、设计模式(23种)**2.1 责任链模式 2.2 过滤器墨海 2.3 公布订阅模式 2.4 工厂模式** 3、工程治理**3.1 Makefile/cmake/configure 3.2 git /svn与继续集成 3.3 Linux零碎运行时命令** 二、高性能网络设计 1、代码实现**1.1 网络io与select/poll/epoll 1.2 reactor的原理与实现 1.3 http/https web服务器的实现 1.4 websocket协定与服务器实现** 2、计划剖析**2.1 服务器百万并发的实现(c10K,c1000k, C10M) 2.2 redis/memcached/Nginx网络组件 2.3 Posix API与网络协议栈 2.4 UDP牢靠协定 QUIC/KCP** 三、根底组件实现 1、池式构造 **1.1 手写线程池 1.2 内存池 ringbuffer 1.3 异步申请池 性能优化,异步mysql 异步dns 异步redis 1.4 mysql连接池 1.5 redis连接池**2、高性能组件 **2.1 原子操作 CAS 2.2 音讯队列与无锁队列 2.3 定时器的计划 红黑树 工夫轮 最小堆 2.4 锁的实现原理 互斥锁,自旋锁 ,乐观锁,乐观锁,分布式锁 2.5 服务器连贯保活 keepalived 2.6 try/catch的实现**3、开源组件 **3.1 libevent/libev框架 3.2 异步日志计划 log4cpp 3.3 应用层协定 protobuf/thrift 3.4 openssl加密 3.5 json与xml解析器 3.6 字符编码unicode/gbk/utf-8** 四、零声自研框架 ...

November 3, 2020 · 2 min · jiezi

关于c++:DPDK性能优化技术汇总以及学习路线

Memory AccessAddress Alignment在内存中存取一个变量最高效的形式是将其放在一个能够被它的长度整除的地址上。 (void *)&variable % sizeof(variable) == 0 所谓的按某个长度对齐就是这个意思。GCC编译器会主动帮咱们解决这些事件。比拟非凡的形式是将一个大型的构造体,或者动态数组按64byte的形式对齐: int BigArray[1024] __attribute__((aligned(64))); 这次要是思考到CPU的Cache Line长度多为64byte,变量按64对齐能够使其正好开始于一个Cache Line,缩小Cache Miss/False Sharing以及利用CPU的高级指令集并行计算。 Note: _attribute _((aligned(x)))有时只对全局变量无效,而对局部变量有效。Huge Page大页技术是以后风行的一种性能优化技术。在Linux零碎中有一套简单的过程虚拟地址和内存物理地址的转换机制,简单的细节咱们不去关怀,只须要晓得Linux是通过页(Page)这一机制(Look-up table)来确立两者的对应关系的。简略的类比就是在一本2000页的书中找到某一个章节,远比在一本2页的书中简单。思考到传统页面4KB的大小和大页2GB的小大之差,这个类比还不是那么失当。在CPU中,须要以缓存的模式存储一些转换关系,这种缓存成为TLB Cache。应用大页能够缩小TLB Cache Miss。 Virtual addr maps to physical addr Note: Huge Page能够在绝大部分状况之下进步性能,但并不是所有状况下都能够起到晋升性能的成果。对于内存,须要综合思考各种因素,进步性能的根本策略还是以空间换工夫。具体的剖析文章请DPDK学习路线以及视频解说+qun832218493获取====================================================== 1.dpdk PCI原理与testpmd/l3fwd/skeletion 2.kni数据流程 3.dpdk实现dns 4.dpdk高性能网关实现 5.半虚拟化virtio/vhost的减速 NUMA严格来说NUMA并不是一种性能优化技术,而是一种内存架构。 NUMA Architecture 每一个CPU Core都与它本地连接的内存间接相连,独享总线,具备最快的读写速度。如果去近程(remote)内存去读写的话,则须要跨CPU Core执行。在DPDK中,有一整套精美且高效的内存调配和管理机制,联合大页和NUMA等机制,根本准则是,将一个CPU Core须要解决的数据都放在离它最近的内存上。相干的实现能够参考DPDK中memseg memzone等内存机制相干代码的实现,这里能够有专门文章介绍。 Polling Mode Drive(PMD)是DPDK实现的优化Linux网络接管发送性能的模块,官网有具体的介绍材料。Click Memory Pool对于须要频繁填充开释的内存空间能够采纳内存池的形式事后动态分配一整块内存区域,而后对立进行治理,从而省去频繁的动态分配和开释过程,既进步了性能,同时也缩小了内存碎片的产生。内存池多以队列的模式组织闲暇或占用内存。在DPDK中,还思考了地址对齐,以及CPU core local cache等因素,以晋升性能。 这里提到的内存对齐不同于后面仅仅将变量放在一个适合的地址“数目”上,而是综合思考了内存通道(channel)和rank,将变量(比方一个三层网络的Pkt),均匀散布于不同的channel之上(多依附padding),能够缩小channel拥塞,显著晋升性能。如图: Two Channels and Quad-ranked DIMM Example ...

November 3, 2020 · 2 min · jiezi

关于c++:大专毕业CC零基础学编程难吗多久能就业

一、艰深地了解什么是编程语言学习编程语言之前,首先要搞清楚「编程语言」这个概念。 很小的时候,父母就教咱们闭口谈话,也教咱们如何了解他人讲话的意思。通过长时间的陶冶和自我学习,咱们居然在人不知;鬼不觉中学会了谈话,同时也能听懂其余小朋友谈话的意思了,咱们开始向父母要零花钱买零食和玩具、被欺侮了向父母倾诉…… 咱们说的是汉语,是“中国语言”,只有把咱们的需要通知父母,父母就会满足,咱们用“中国语言”来管制父母,让父母做咱们喜爱的事件。 “中国语言”有固定的格局,每个汉字代表的意思不同,咱们必须正确的表白,父母能力了解咱们的意思。例如让父母给咱们10元零花钱,咱们会说“妈妈给我10块钱吧,我要买小汽车”。如果咱们说“10元给我汽车小零花钱妈妈”,或者“妈妈给我10亿人民币,我要买F-22”,妈妈就会感觉奇怪,听不懂咱们的意思,或者了解谬误,指责咱们。 咱们通过有固定格局和固定词汇的“语言”来管制别人,让他人为咱们做事件。语言有很多种,包含汉语、英语、法语、韩语等,尽管他们的词汇和格局都不一样,然而能够达到同样的目标,咱们能够抉择任意一种语言去管制别人。 同样,咱们也能够通过”语言“来管制计算机,让计算机为咱们做事件,这样的语言就叫做编程语言(Programming Language)。 编程语言也有固定的格局和词汇,咱们必须通过学习才会应用,能力管制计算机。 编程语言有很多种,罕用的有C语言、C++、Java、C#、Python、PHP、JavaScript、Go语言、Objective-C、Swift、汇编语言等,每种语言都有本人善于的方面,例如: 能够将不同的编程语言比喻成各国语言,为了表白同一个意思,可能应用不同的语句。例如,表白“世界你好”的意思: 汉语:世界你好;英语:Hello World法语:Bonjour tout le monde在编程语言中,同样的操作也可能应用不同的语句。例如,在屏幕上显示“C语言”: C语言:puts("C语言");PHP:echo "C语言";Java:System.out.println("C语言");编程语言相似于人类语言,由直观的词汇组成,咱们很容易就能了解它的意思,例如在C语言中,咱们应用 puts 这个词让计算机在屏显示出文字;puts 是 output string(输入字符串)的缩写。 应用 puts 在屏幕上显示“C语言”: puts("C语言"); 咱们把要显示的内容放在("和")之间,并且在最初要有;。你必须要这样写,这是固定的格局。 小总结:编程语言是用来管制计算机的一系列指令(Instruction),它有固定的格局和词汇(不同编程语言的格局和词汇不一样),必须恪守,否则就会出错,达不到咱们的目标。 C语言(C Language)是编程语言的一种,学习C语言,次要是学习它的格局和词汇。上面是一个C语言的残缺例子,它会让计算机在屏幕上显示”C语言“。 这个例子次要演示C语言的一些固有格局和词汇,看不懂的读者不用深究,也不用问为什么是这样,后续咱们会逐渐给大家解说。 #include <stdio.h>int main(){ puts("C语言"); return 0;} 这些具备特定含意的词汇、语句,依照特定的格局组织在一起,就形成了源代码(Source Code),也称源码或代码(Code)。 那么,C语言必定规定了源代码中每个词汇、语句的含意,也规定了它们该如何组织在一起,这就是语法(Syntax)。它与咱们学习英语时所说的“语法”相似,都规定了如何将特定的词汇和句子组织成能听懂的语言。 编写源代码的过程就叫做编程(Program)。从事编程工作的人叫程序(Programmer)。程序员也很风趣,喜爱自嘲,常常说本人的工作辛苦,位置低,像农民一样,所以称本人是”码农“,就是写代码的农民。也有人自嘲称是”程序猿“。 二、C语言到底是一门怎么的语言?对于大部分程序员,C语言是学习编程的第一门语言,很少有不理解C的程序员。 C语言除了能让你理解编程的相干概念,带你走进编程的大门,还能让你明确程序的运行原理,比方,计算机的各个部件是如何交互的,程序在内存中是一种怎么的状态,操作系统和用户程序之间有着怎么的“爱恨情仇”,这些底层常识决定了你的倒退高度,也决定了你的职业生涯。 如果你心愿成为超群绝伦的人才,而不仅仅是码农,这么这些常识就是不可逾越的。也只有学习C语言,能力更好地理解它们。有了足够的根底,当前学习其余语言,会举一反三,很快上手,7 天理解一门新语言不是神话。 C语言概念少,词汇少,蕴含了根本的编程元素,起初的很多语言(C++、JAVA等)都参考了C语言,说C语言是古代编程语言的开山鼻祖毫不夸大,它扭转了编程世界。 正是因为C语言的简略,对初学者来说,学习老本小,工夫短,联合本教程,可能疾速把握编程技术。在世界编程语言排行榜中,C语言、Java 和 C++ 霸占了前三名,领有绝对优势,如下表所示: 三、C语言难吗?和 Java、C++、Python、C#、JavaScript 等高级编程语言相比,C语言波及到的编程概念少,附带的规范库小,所以整体比拟简洁,容易学习,非常适合初学者入门。 编程语言的倒退大略经验了以下几个阶段: 汇编语言 --> 面向过程编程 --> 面向对象编程 汇编语言是编程语言的开荒年代,它十分底层,间接和计算机硬件打交道,开发效率低,学习老本高;C语言是面向过程的编程语言,曾经脱离了计算机硬件,能够设计中等规模的程序了;Java、C++、Python、C#、PHP 等是面向对象的编程语言,它们在面向过程的根底上又减少了很多概念。C语言呈现的时候,曾经度过了编程语言的开荒年代,具备了古代编程语言的个性,然而这个时候还没有呈现“软件危机”,人们没有能源去开发更加高级的语言,所以也没有太简单的编程思维。 ...

November 3, 2020 · 1 min · jiezi

关于c++:TarsCpp-组件之-MySQL-操作

作者 Eaton 导语 在后盾开发中,咱们常常须要和数据库打交道,而在 C++ 开发中,MySQL Connector/C++ 只提供了根底操作接口,简单的业务经常须要一系列简单的调用过程,非常容易出错,那有什么办法能够防止呢?TarsCpp 中提供了数据库操作类 TC_Mysql,使咱们可能不便地进行数据库操作,进步业务开发效率。本文将对 TC_Mysql 进行介绍剖析。 目录MySQL 简介MySQL 罕用 API存在的问题TC_Mysql 数据库配置接口 TC_DBConf数据库操作类 TC_Mysql 构造函数MySQL 操作函数数据存储类 MysqlRecord 与 MysqlData数据库异样类 TC_Mysql_ExceptionMySQL简介数据库是计算机利用零碎中一种专门治理数据资源的零碎,以数据为核心,解决了传统文件存储数据存在的数据冗余、移植性差等问题。在后盾开发中,数据库操作具备十分重要的位置,不可避免地须要和数据库打交道。当初市面上的数据库软件多种多样,最罕用的便是 MySQL。它是一款平安、跨平台、高效的关系型数据库系统,由瑞典的 MySQL AB 公司开发、公布并反对。因为其体积小、速度快、总体领有成本低,尤其是开放源码这一特点,使得很多公司都采纳 MySQL 数据库以降低成本。 数据库的根底操作包含增、删、改、查四种操作,对应的在 MySQL 中为 Insert, Delete, Update, Select 等,可能不便地实现对数据库中数据的治理。 MySQL 罕用 APIMySQL 反对了各种支流的程序设计语言,提供了丰盛的数据库操作 API 函数。在 C++ 开发中,MySQL 官网提供了相干的数据库连贯动静库 MySQL Connector/C++,接口定义在 mysql.h 中,蕴含 MySQL 根底操作 API,像罕用的 mysql_real_connect, mysql_real_query, mysql_store_result, mysql_fetch_row 等。其中 mysql_real_connect 用于创立到 MySQL 数据库服务的连贯;mysql_real_query 用于执行 MySQL 语句;mysql_store_result 用于将执行后果保留到本地;mysql_fetch_row 用于获取返回后果中的行。这四个函数个别状况下可能满足大部分需要,它们在 mysql.h 中的申明如下 ...

November 2, 2020 · 6 min · jiezi

关于c++:TarsCpp-组件-之-智能指针详解

作者 Eaton 导语 在 C++ 中,内存治理是非常重要的问题,一不小心就会造成程序内存泄露,那么怎么防止呢?通过智能指针能够优雅地治理内存,让开发者只须要关注内存的申请,内存的开释则会被主动治理。在文章 开源微服务框架 TARS 之 根底组件 中曾经简要介绍过,TARS 框架组件中没有间接应用 STL 库中的智能指针,而是实现了本人的智能指针。本文将会别离对 STL 库中的智能指针和 TarsCpp 组件中的智能指针进行比照剖析,并具体介绍 TARS 智能指针的实现原理。 目录智能指针 简介援用计数原理STL 库中的智能指针 shared_ptrTARS 智能指针 TC_AutoPtr 实现详解 原子计数类 std::atomic智能指针基类 TC_HandleBase智能指针模板类 TC_AutoPtrTC_AutoPtr 劣势智能指针简介在计算机程序中,泄露是常见的问题,包含内存泄露和资源泄露。其中资源泄露指的是零碎的 socket、文件描述符等资源在应用后,程序不再须要它们时没有失去开释;内存泄露指的是动态内存在应用后,程序不再须要它时没有失去开释。 内存泄露会使得程序占用的内存越来越多,而很大一部分往往是程序不再须要应用的。在 C++ 程序中,内存泄露常见于咱们应用了 new 或者 malloc 申请动静存储区的内存,却忘了应用 delete 或者 free 去开释内存,造成零碎内存的节约,导致程序运行速度减慢甚至零碎解体等严重后果。 随着计算机利用需要的日益减少,利用的设计与开发日趋简单,开发人员在开发过程中解决的变量也越来越多。如何无效进行内存调配和开释、避免内存透露逐步成为开发者面临的重要难题。为了解决遗记手动开释内存造成的内存泄露问题,智能指针诞生了。 常见的智能指针的应用场景,包含类中的成员变量(指针型)和一般的变量(指针型)。智能指针能够实现指针指向对象的共享,而无需关注动态内存的开释。通用实现技术是援用计数(Reference count),下一部分会介绍,简略讲就是将一个计数器与类指向的对象相关联,跟踪有多少个指针指向同一对象,新增一个指针指向该对象则计数器 +1,缩小一个则执行 -1。 援用计数原理 援用计数是智能指针的一种通用实现技术,上图为大抵流程,基本原理如下: 在每次创立类的新对象时,初始化指针并将援用计数置 1;当对象作为另一对象的正本而创立时(复制构造函数),复制对应的指针并将援用计数 +1;当对一个对象进行赋值时,赋值操作符 = 将左操作数所指对象的援用计数 -1,将右操作数所指对象的援用计数 +1;调用析构函数数,援用计数 -1;上述操作中,援用计数减至 0 时,删除根底对象;STL 库中的智能指针 shared_ptr 和 TARS 智能指针都应用了该援用计数原理,前面会进行介绍。 ...

November 2, 2020 · 5 min · jiezi

关于c++:Linux内核深入理解红黑树与B树应用场景

一、红黑树和B树利用场景有何不同?两者都是有序数据结构,可用作数据容器。红黑树多用在外部排序,即全放在内存中的,微软STL的map和set的外部实现就是红黑树。B树多用在内存里放不下,大部分数据存储在外存上时。因为B树层数少,因而能够确保每次操作,读取磁盘的次数尽可能的少。在数据较小,能够齐全放到内存中时,红黑树的工夫复杂度比B树低。反之,数据量较大,外存中占次要局部时,B树因其读磁盘次数少,而具备更快的速度。 (1)红黑树,B树,B+树,B-树具体了解:1.红黑树rbtree 二叉排序树map 就是采纳红黑树存储的,红黑树(RB Tree)是均衡二叉树,其长处就是树到叶子节点深度统一,查找的效率也就一样,为logN.在履行查找,插入,删除的效率都统一,而当是全副静态数据时,没有太多劣势,可能采纳hash表各适合。hash_map是一个hash table占用内存更多,查找效率高一些,然而hash的工夫比拟费时。总 体来说,hash_map 查找速度会比map快,而且查找速度根本和数据数据量大小,属于常数级别;而map的查找速度是log(n)级别。并不一定常数就比log(n)小, hash还有hash函数的耗时,明确了吧,如果你思考效率,特地是在元素达到肯定数量级时,思考思考hash_map。但若你对内存应用特地严格,心愿程序尽可能少耗费内存,那么肯定要小心,hash_map可能会让你陷入难堪,特地是当你的hash_map对象特地多时,你就更无法控制了,而且 hash_map的结构速度较慢。当初晓得如何抉择了吗?衡量三个因素: 查找速度, 数据量, 内存应用。trie树Double Array 字典查找树Trie树既可用于个别的字典搜寻,也可用于索引查找。每个节点相当于DFA的一个状态,终止状态为查找完结。有序查找的过程相当于状态的一直转换对于给定的一个字符串a1,a2,a3,…,an.则采纳TRIE树搜寻通过n次搜寻即可实现一次查找。不过如同还是没有B树的搜寻效率高,B树搜索算法复杂度为logt(n+1/2).当t趋势大,搜寻效率变得高效。怪不得DB2的拜访内存设置为虚拟内存的一个PAGE大小,而且帧切换频率升高,无需常常的PAGE切换。2.B树即二叉搜寻树: 1.所有非叶子结点至少领有两个儿子(Left和Right);2.所有结点存储一个关键字;3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;如:B树的搜寻,从根结点开始,如果查问的关键字与结点的关键字相等,那么就命中;否则,如果查问关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入右儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字;如果B树的所有非叶子结点的左右子树的结点数目均放弃差不多(均衡),那么B树的搜寻性能迫近二分查找;但它比间断内存空间的二分查找的长处是,扭转B树结构(插入与删除结点)不须要挪动大段的内存数据,甚至通常是常数开销;如:但B树在通过屡次插入与删除后,有可能导致不同的构造:左边也是一个B树,但它的搜寻性能曾经是线性的了;同样的关键字汇合有可能导致不同的树结构索引;所以,应用B树还要思考尽可能让B树放弃左图的构造,和防止右图的构造,也就是所谓的“均衡”问题; 理论应用的B树都是在原B树的根底上加上均衡算法,即“均衡二叉树”;如何放弃B树结点散布平均的均衡算法是均衡二叉树的要害;均衡算法是一种在B树中插入和删除结点的策略;3.B-树是一种多路搜寻树(并不是二叉的): 1.定义任意非叶子结点最多只有M个儿子;且M>2;2.根结点的儿子数为[2, M];3.除根结点以外的非叶子结点的儿子数为[M/2, M];4.每个结点寄存至多M/2-1(取上整)和至少M-1个关键字;(至多2个关键字);5.非叶子结点的关键字个数=指向儿子的指针个数-1;6.非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];7.非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;8.所有叶子结点位于同一层;如:(M=3)B-树的搜寻,从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则完结,否则进入查问关键字所属范畴的儿子结点;反复,直到所对应的儿子指针为空,或曾经是叶子结点;B-树的个性: 1.关键字汇合散布在整颗树中;2.任何一个关键字呈现且只呈现在一个结点中;3.搜寻有可能在非叶子结点完结;4.其搜寻性能等价于在关键字选集内做一次二分查找;5.主动档次管制;因为限度了除根结点以外的非叶子结点,至多含有M/2个儿子,确保了结点的至多利用率,其最底搜寻性能为:其中,M为设定的非叶子结点最多子树个数,N为关键字总数;所以B-树的性能总是等价于二分查找(与M值无关),也就没有B树均衡的问题;因为M/2的限度,在插入结点时,如果结点已满,须要将结点决裂为两个各占M/2的结点;删除结点时,需将两个有余M/2的兄弟结点合并;4.B+树B+树是B-树的变体,也是一种多路搜寻树: 1.其定义根本与B-树同,除了;2.非叶子结点的子树指针与关键字个数雷同;3.非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间);5.为所有叶子结点减少一个链指针;6.所有关键字都在叶子结点呈现;如:(M=3)B+的搜寻与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树能够在非叶子结点命中),其性能也等价于在关键字选集做一次二分查找;B+的个性: 1.所有关键字都呈现在叶子结点的链表中(浓密索引),且链表中的关键字恰好是有序的;2.不可能在非叶子结点命中;3.非叶子结点相当于是叶子结点的索引(稠密索引),叶子结点相当于是存储(关键字)数据的数据层;4.更适宜文件索引零碎;5.B树是B+树的变体,在B+树的非根和非叶子结点再减少指向兄弟的指针;B树定义了非叶子结点关键字个数至多为(2/3)M,即块的最低使用率为2/3(代替B+树的1/2);B+树的决裂:当一个结点满时,调配一个新的结点,并将原结点中1/2的数据复制到新结点,最初在父结点中减少新结点的指针;B+树的决裂只影响原结点和父结点,而不会影响兄弟结点,所以它不须要指向兄弟的指针;B树的决裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最初批改父结点中兄弟结点的关键字(因为兄弟结点的关键字范畴扭转了);如果兄弟也满了,则在原结点与兄弟结点之间减少新结点,并各复制1/3的数据到新结点,最初在父结点减少新结点的指针;所以,B树调配新结点的概率比B+树要低,空间使用率更高;小结B树:二叉树,每个结点只存储一个关键字,等于则命中,小于走左结点,大于走右结点;B-树:多路搜寻树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范畴的子结点;所有关键字在整颗树中呈现,且只呈现一次,非叶子结点能够命中;B+树:在B-树根底上,为叶子结点减少链表指针,所有关键字都在叶子结点中呈现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;B树:在B+树根底上,为非叶子结点也减少链表指针,将结点的最低利用率从1/2进步到2/3; B树是为了进步磁盘或内部存储设备查找效率而产生的一种多路均衡查找树。B+树为B树的变形构造,用于大多数数据库或文件系统的存储而设计。 二、B树绝对于红黑树的区别在大规模数据存储的时候,红黑树往往呈现因为树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的状况。为什么会呈现这样的状况,咱们晓得要获取磁盘上数据,必须先通过磁盘移动臂挪动到数据所在的柱面,而后找到指定盘面,接着旋转盘面找到数据所在的磁道,最初对数据进行读写。磁盘IO代价次要破费在查找所需的柱面上,树的深度过大会造成磁盘IO频繁读写。依据磁盘查找存取的次数往往由树的高度所决定,所以,只有咱们通过某种较好的树结构缩小树的构造尽量减少树的高度,B树能够有多个子女,从几十到上千,能够升高树的高度。 三、B树和B+树的区别B树:所有叶子结点都呈现在同一层,叶子结点不蕴含任何关键字信息。B+树:所有的叶子结点中蕴含了全副关键字的信息,及指向含有这些关键字记录的指针,且叶子结点自身依关键字的大小自小而大的程序链接,所有的非终端结点能够看成是索引局部,结点中仅含有其子树根结点中最大(或最小)关键字。 (而B 树的非终节点也蕴含须要查找的无效信息) 为什么说B+比B树更适宜理论利用中操作系统的文件索引和数据库索引? 1) B+的磁盘读写代价更低 B+的外部结点并没有指向关键字具体信息的指针。因而其外部结点绝对B树更小。如果把所有同一外部结点的关键字寄存在同一盘块中,那么盘块所能包容的关键字数量也越多。一次性读入内存中的须要查找的关键字也就越多。相对来说IO读写次数也就升高了。 2) B±tree的查问效率更加稳固 因为非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查问的门路长度雷同,导致每一个数据的查问效率相当。 数据库索引采纳B+树的次要起因是 B树在进步了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。正是为了解决这个问题,B+树应运而生。B+树只有遍历叶子节点就能够实现整棵树的遍历。而且在数据库中基于范畴的查问是十分频繁的,而B树不反对这样的操作(或者说效率太低)。 本群收费分享学习材料(C/C++,Linux,golang,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,ffmpeg,TCP/IP,协程,DPDK,嵌入式)等;交换探讨支付材料请加群Q:1106675687课程地址:https://ke.qq.com/course/4177...。

November 2, 2020 · 1 min · jiezi

关于c++:浅谈如何阅读Linux源码新手必备

经常有人问:我想学习内核,须要什么根底吗?Linus Torvalds自己是这样答复的:你必须应用过Linux。 这个……还是有点太泛了吧,我想上面几个根底可能还是须要的,只管不肯定必须: 1, 对于操作系统实践的最高级的常识。不须要通读并了解《操作系统概念》《古代操作系统》等巨著,但总要晓得分时(time-shared)和实时(real-time)的区别是什么,过程是个什么货色,CPU和系统总线、内存的关系(很粗略即可),等等。 2, 对于C语言。不须要曾经很精通C语言,只有能纯熟编写C程序,能看懂链表、散列表等数据结构的C实现,用过gcc编译器,就能够了。当然,如果曾经精通C语言显然是大占便宜的。 3, 对于CPU的常识。这块儿能够在学习内核过程中补,但这样的话你就须要看解说很具体的书,比如前面将会提到的《情景剖析》。你是否相熟 Intel 80386 CPU?尝试着答复这几个问题来判断一下:1)说出80386的中断门和陷阱门的区别;2)说出保护模式与实模式的区别;3)多处理器机器上,一般的读-改-写回一块内存这样的动作,为什么须要非凡的伎俩来爱护。等等。解说基于其它CPU的Linux内核的书,目前好象只有一本《IA64Linux内核:设计与实现》──也还是Intel的,其它都是解说基于IA32的。 以上算是常识方面吧,如果还要再补充一条,我想就是:入手编译过内核。 好了,咱们接下来走。好多人装上Linux之后,第一件事找到内核源码所在的门路,关上一个C程序文件,开始哗哗哗翻页,看看赫赫有名的Linux内核代码到底长啥模样──而后敞开。这是可了解的,但却不是学习的办法。刚开始,必须从读书动手。[color=red]至多要对内核有一个Overview 之后,才有可能带着问题去试图浏览源代码自身。 [/color]上面就讲一下我读过的几本书: 1, 《Linux内核设计与实现》,英文名Linux Kernel Development(所以有人叫它LKD),机械工业出版社,¥35, 美国Robert Love著,陈莉君译者。 评说: 此书是当今名列前茅的入门最佳图书。作者是为2.6内核退出了抢占的人,对调度局部十分精通,而调度是整个零碎的外围,因而本书是很权威的。这本书解说浅显易懂,全书没有列举一条汇编语句,然而给出了整个Linux操作系统2.6内核的概观,使你能通过浏览迅速取得一个overview。而且对内核中较为凌乱的局部(如下半部),它的解说是最透彻的。对没怎么深刻内核的人来说,这是强烈推荐的一本书。 翻译:翻译程度、负责任水平都不错,然而印刷存在一些谬误。买了此书的敌人能够参考我在Linux高级利用版的《Linux内核设计与实现中文版勘误》:http://bbs.chinaunix.net/forum/viewtopic.php?t=541234另外,此书2005年有了第二版,目前尚无中译本面世。我就是对照着2nd-en勘误1st-cn的。 2, 《Linux内核源代码情景剖析》上、下。毛德操、胡希明著,浙江大学出版社,上册¥80,下册¥70. 评说: 本书是基于2.4.0内核的,比拟早,也没据说会出第二版。上册解说内存治理、中断、异样与零碎调用、过程管制、文件系统与传统Unix IPC;下册解说socket、设施驱动、SMP和疏导。对于这套书的评估褒贬不一,我集体认为其深度是同类著述中最优良的。本书基于Intel IA32体系,因为厚度大,很多体系上的常识都捎带解说了,所以如果你想深刻理解内核的工作机制而又不十分相熟Intel CPU的体系结构,本书是最合适的。毛病是:版本较老,没有TCP/IP协定栈局部(它讲的socket只是Unix域协定的),图表太少,不适宜初学者入门。还有就是对学生敌人来说,可能书价偏高,这样的话能够思考先买上册,因为上册是外围局部,下册一大部分都在讲具体PCI/ISA/USB设施的驱动。 翻译:没什么翻译,作者是国人,而且行文流畅。自己书桌上诸多计算机经典图书当中,这套是惟一又经典又无阅读障碍的。 http://www.linuxforum.net内核版好多敌人曾经把这书读到六七遍了,我很羞愧,上册差不多读熟了,下册就SMP局部还看过──但这就破费了整整1年的工夫,还有好多弄不懂的。这里顺便阐明另外一个钻研内核常见的误区:指标太宏大。要晓得Linux内核(最新的2.6.13)bzip2压缩之后 37M,解压缩之后244M,基本不是哪个人可能吃透的。即便是内核的外围开发团队中,恐怕也只Linus Torvalds、Alan Cox、 David Miller、Ingo Molnar寥寥数人会有比拟全面的理解,其它人都是做本人专门的局部。 我本人来说,目前曾经决定放弃内存治理的全副(slab层、LRU、rbtree等)、文件系统局部、外设驱动局部,临时也没打算弄IA32以外的其它体系的局部。 3, 《深刻了解Linux内核》第二版。中国电力出版社。也是陈莉君译。此书是Linux内核黑客在举荐图书时的首选。 评说: 此书C版的converse兄送了我一本第一版,因而就没买第二版,比拟悔恨。因而只就第一版说一说,第一版基于2.2,第二版2.4 。我见 O’Reilly官方主页上说第三版的英文版将于2005年11月出版,也不知咱们何时能力见到。此书图表很多,形象地给出了要害数据结构的定义,与《情景剖析》相比,本书内容紧凑,不会一个问题解说动辄上百页,有提纲挈领的功能,然而深度上要逊于《情景剖析》。 4, 其它的几本书。市面上能见到的其它的Linux内核的图书,象《Linux设施驱动程序》、《Linux内核源代码齐全正文》以及新出的《Linux内核剖析及编程》等。 《Linux设施驱动程序》第二版是基于2.4的,中文翻译不错,中国电力出版。这书强调入手实际,但它是解说“设施驱动”的,不是最外围的货色,而且有些货色没硬件的话无奈实际,可能更适宜驱动开发的程序员吧,不太适宜那些For fun and profit的人。此书有第三版英文版,东南大学出版社影印,解说2.6的,行文流畅,解说的面也比第二版更宽泛,我读过其中对于同步与互斥、内存调配的局部,感觉很不错。 《Linux内核源代码齐全正文》(机械工业出版社)是同济大学的博士生赵炯的著述,解说0.1Linux内核,我没买也没看,有看过的敌人说一说。 《Linux内核剖析及编程》(电子工业出版社)是刚刚出版的,国人写的,解说2.6.11 。很多人说好,但有人说不够零碎,我没买,不敢评说。 还有一本清华出的《Linux内核编程指南(第三版)》,原书应该是好书,然而翻译、排版非常糟烂,脱字跳行,基本没法看,我买了一本又扔掉了。 5, 其它资源。 TLDP(The Linux Documentation Project)有大量文档,其中不少是对于内核的,有些是在国外出版过的,象《Linux Kernel Interls》《The Linux Kernel》《Linux Kernel Module Programming Guide》等,作者都是亲自加入开发的人,著述较为可信。Http://www.linuxforum.net 中国Linux论坛的内核版。该版是钻研内核的中文Linux社区中程度最高的,有很多专家级别的牛人,强烈推荐去学习一下(但倡议不要问太过分简略的问题,人家脾气再好也会烦的^_^),它的置顶贴几乎是一个无所不包的FAQ,精华区也有很多材料。只惋惜太过曲高和寡,人气不是很旺。 ...

November 2, 2020 · 1 min · jiezi

关于c++:C-面向对象程序设计复习大纲

1.叙述面向对象编程的特点是什么?(提醒:封装、继承、多态。) 比照面向过程具备形象、封装、继承和多态的特点。 封装是将形象失去的数据和行为相结合,造成了一个有机整体,使得一部分成员充当类与内部的接口,而将其余成员暗藏了起来达到了对成员拜访权限的正当管制,使得不同类之间的影响最小,增强数据安全,简化编程。 继承容许在放弃原有类个性的根底上,进行更具体、更具体的阐明,可能很好反映出非凡概念和个别概念之间的关系,是代码复用的根底机制。 多态使得一段程序可能具备解决多种类型对象的能力,雷同的音讯在不同的对象下会有不同的动作,加强了编程的灵活性。 2.应用const定义常量与用应用define定义常量相比,有什么长处? a. const常量有数据类型,而宏常量没有数据类型。编译器能够对const常量进行类型安全检查,而对宏常量只能字符替换 b. 有些集成化的调试工具能对const常量进行调试,对宏常量不能调试 c.const定义的常量在程序运行的过程中只有一份拷贝,而define定义的常量在内存中有若干拷贝。 3.用代码阐明在规范C++中如何进行输入输出,并解释各语句的含意是什么? cout<<"hello!"<<"world";cin>>a>>b; 在输出时,从键盘输入的数据先放在键盘缓冲区中,当按回车键时,键盘缓冲区中的数据输出到程序中的输出缓冲区,造成cin流,而后用流提取运算符“>>”从输出缓冲区中提取数据送给程序中的无关变量。 当用cout和流插入运算符“<<”向显示器输入数据时,先将这些数据送到程序中的输入缓冲区保留,直到缓冲区满了或遇到endl,就将缓冲区中的全副数据送到显示器显示进去。 4.C++中如何进行动态类型转换,解释并举例说明。 (1)用于类层次结构中基类和派生类之间指针或援用的转换。进行上行转换(把派生类的指针或援用转换成基类示意)是平安的;进行上行转换(把基类指针或援用转换成派生类示意)时,因为没有动静类型查看,所以是不平安的。 class Base { }; class Derived:public Base {}; int main(){ Derived D; Base* B = static_cast<Base*> (&D); return 0;}将派生类型的指针转化为基类型的指针 (2)用于根本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保障。 double a; int b=100; a = static_cast<double> (b);(3)把空指针转换成指标类型的空指针(不平安!!)。 (4)把任何类型的表达式转换成void类型。 5.论述C++中函数三种调用的形式实现机制、特点及其实参、形参的格局,最好用代码阐明。(提醒:传址、传值、援用传递) 在C++中调用函数时有三种参数传递形式: (1)传值调用; int main( ){ void swap(int,int); //函数申明 int i=3,j=5; swap(i,j); //调用函数swap return 0;} void swap(int a,int b) //希图通过形参a和b的值调换,实现实参i和j的值调换{ int temp; temp=a; //以下3行用来实现a和b的值调换 a=b; b=temp;}(2)传址调用(传指针); ...

November 2, 2020 · 5 min · jiezi

关于c++:打造可复用的数据结构库2-异常类族的构建

1 为什么有异样类族 在程序的逻辑解决的时候,会有一些异样的景象,这种状况,咱们只能预测他可能呈现,然而却无奈彻底的防止,则就要在一些会出现异常的中央做些进攻,一旦出现异常,就要有相应的解决对策。 2 异样类的构建 一个工程中,代码的逻辑是盘根错节,则就要有肯定的章程来治理异样的解决,这样,能够帮忙咱们的程序看起来洁净整洁。在当初的工程中,常见的异样个别有: 计算异样;例如做了除以0的操作空指针异样:例如对空指针做了不非法的操作拜访越界异样内存不足异样参数谬误异样 异常情况的整顿与分类,咱们能够看出,这些异样有肯定的共性,但也有不同的中央。咱们就利用C++语言语言的继承与多态的个性,做一个根底的异样类,而后各个类从根底类继承,而后本人增加本人的个性。 2.1 异样类的基类构建2.1.1 提醒函数 既然是异样的类,他的呈现,就是为了告警,那么就会有一些提示信息,理论应用的应用,都是抛出异样的中央输出一些提醒语句。那么构建类的时候,就要设计提醒语句的输出的中央。 Exceptional(const char *message);Exceptional(const char *file, int line);Exceptional(const char *message, const char *file,const int line);virtual const char *message() const;virtual const char * location( ) const ; 从这三个构建函数的样子能够看出,根本是一样的,就是个别的参数没有而已,为了代码的复用,能够写一个专用的公有函数来做三个构建函数的实现。 void init(const char *message, const char *file, int line);2.1.2 属性工能函数 既然是类,就要合乎C++的类的个别共性,然而该类在 赋值操作的时候,或者拷贝结构的时候,就须要非凡解决,则须要对这两个工能做解决 Exceptional(const Exceptional& obj);Exceptional& operator = ( const Exceptional& obj);2.2 类的架构 以上的形容曾经根本能够结构这个类了,然而有个细节要留神,就是在传入的字符串存储空间是无奈确定的。为了避免意外,该类要对传入的字符串做一个复制,在函数被析构的时候,就要开释。所以类的结构如下。 class Exceptional { protected: char* m_message=nullptr; char* m_location =nullptr; void init(const char *message, const char *file, int line); public: Exceptional(const char *message); Exceptional(const char *file, int line); Exceptional(const char *message, const char *file,const int line); Exceptional(const Exceptional& obj); Exceptional& operator = ( const Exceptional& obj); virtual const char *message() const; virtual const char * location( ) const ; virtual ~Exceptional() =0 ; };3基类的实现 void Exceptional :: init(const char *message, const char *file, const int line) { //因为不能保障传进来的 message 的空间,所以复制一份存到堆中 m_message= strdup(message); if(file != NULL) { char sl[16]={0}; itoa(line,sl,10); m_location=reinterpret_cast< char * >(malloc( strlen( file ) +strlen( sl)+2 ) ) ; m_location = strcpy(m_location,file); m_location = strcat (m_location ,";" ); m_location = strcat (m_location ,sl ); } else { m_location=nullptr; } } Exceptional :: Exceptional(const char *message) { init( message, NULL, NULL); } Exceptional :: Exceptional(const char *file, int line) { init( NULL, file, line); } Exceptional :: Exceptional( const char *message, const char *file,const int line) { init( message, file, line); } Exceptional :: Exceptional( const Exceptional& obj) { m_message= strdup(obj.m_message); m_location= strdup(obj.m_location); } Exceptional& Exceptional :: operator = ( const Exceptional& obj) { if(this != &obj) { free(m_message); free(m_location); m_message= strdup(obj.m_message); m_location= strdup(obj.m_location); } return *this; } const char * Exceptional :: message() const { return m_message; } const char * Exceptional :: location( ) const { return m_location; } Exceptional :: ~Exceptional() { free(m_message); free(m_location); }4 继承类的实现基类实现当前,剩下的就是对各自类的具体实现、 ...

November 1, 2020 · 4 min · jiezi

关于c++:深入了解Clinux工程师的技术需求为你以后的职业发展定方向

一、C++服务器程序员(流媒体后盾,游戏后盾,高性能服务器后盾) 精通C++,STL,Linux等,相熟设计模式;熟练掌握一门脚本语言(Lua, Python, Perl等);对多线程环境编程有肯定的了解,能独立实现服务器端模块的开发、保护和优化;熟练掌握MySQL数据库的开发保护、性能优化;1.精通C++编程,3年以上服务器开发教训; 2.有手机游戏或者PC网游开发教训,有过残缺手游开发教训者优先; 3.精通Socket协定,理解分布式负载和集群类型的服务器框架结构; 4.精通数据库设计; 5.相熟Python或Lua语言。 1、一年以上服务器开发教训,相熟C++语言; 2、相熟TCP/IP协定,相熟网络编程; 3、相熟规范SQL语言,相熟Mysql更佳; 4、相熟linux,熟练掌握linux基本操作命令; 2年以上C++游戏服务器开发方面的工作教训;对TCP协定相干的开发有全面的认知;对多线程的开发相干的问题有全面的认知;有残缺的C++手游服务器开发教训的优先思考;有Linux平台相干开发教训的优先思考;3年以上网络游戏后盾开发教训; 精通Linux操作系统,具备扎实的Linux环境编程能力; 精通C++编程语言并具备丰盛的面向对象编程教训; 精通网络编程并有高并发零碎的开发教训; 相熟MYSQL或其余大型数据库,可能疾速依据需要实现高性能数据库设计; 1、本科以上学历,计算机、通信等相干业余; 2、3年以上Unix/Linux下C/C++开发教训,相熟罕用的数据结构、算法,纯熟应用STL等规范库; 3、相熟Unix/Linux下罕用架构设计办法,相熟流媒体网络协议和格局,包含rtmp、rtsp、sip协定,以及mp4、ts流媒体格式封装; 4、相熟Unix/Linux操作系统原理、常用工具,相熟Mysql/Oracle等数据库治理、开发,SQL调优; 5、全面的软件知识结构(操作系统、软件工程、设计模式、数据结构、数据库系统、网络安全); 6、有大容量通信零碎和大型互联网后盾开发教训者优先。 1)计算机相关业余,精通C++语言;相熟罕用数据结构和算法; 2)相熟Socket、精通TCP/IP协定及编程; 3)具备编写Shell、 Makefile能力,纯熟应用Linux根本命令; 4)相熟Linux操作系统及其环境下的网络通信编程(过程、线程、内存治理、音讯机制等); 5)相熟音视频封装及编解码技术,理解支流的多媒体规范,例如TS、MP4封装、H.264、H.265、FLV、MPEG2、MP3、ACC编码等; 6)相熟HTTP/RTP/RTSP/RTMP/HLS等流媒体传输协定,音视频解码模块与流媒体协定的对接解决; 7)具备广电行业项目管理教训的,有cdn开发教训者优先; 1、本科及以上学学历,相熟C/C++语言,3年以上流媒体零碎开发教训 2、相熟常见多媒体数据解码格局,相熟H264、RTMP、视频切片、音频同步等方面技术; 3、相熟TCP/IP协定,相熟多媒体相干协定(HTTP,RTSP,RTMP,RTP/RTCP,P2P,SIP等); 4、深刻理解互联网视频播放原理,对ffmpeg等框架有理论的应用教训; 5、有视频直播、点播、视频会议、监控安防等方面教训优先 6、相熟Nginx/Squid模块开发优先思考,有FMS等流媒体服务器搭建教训、P2P零碎研发教训、出名优良的视频产品服务端设计和研发教训优先思考 文档视频学习材料获取+qun 720209036 这里有最全的C++工程师的技术需要,你要做哪方面的开发? 二、利用开发工程师windows /linuxc++ (QT和MFC,偏前端) 1、3年以上Visual C++开发教训 2、熟练掌握C、C++、ATL、COM等编程技术。 3、熟练掌握Windows零碎编程,相熟窗口、网络和多线程技术。 两年以上的嵌入式或windows平台QT应用软件开发教训. 相熟QT跨平台框架,QT图形库和相应的开发工具。至多加入过一个残缺的QT我的项目。 具备数据结构、面向对象、多线程和内存治理的根底和教训 把握window/wince开发环境 相熟通用的代码管理工具,例如SVN, Git等 1、2年以上C++开发教训; 2、在Windows开发平台下的客户端开发有丰盛的教训,熟知windows操作系统原理; 3、相熟windows api调用,相熟MFC类,STL规范库,boost库等等; 4、相熟windows音讯体系,相熟罕用的数据结构与算法,独立钻研的能力; 5、纯熟应用MFC异样类对windows结构化进行捕获,能疾速定位公布版本程序的异样,帮忙组内成员疾速定位解体,内存泄露,GDI资源泄露,能应用近程调试定位问题; 6、尤其善于利用各种调试,日志记录,剖析工具对windows下客户端开发的代码进行调试,BUG查找,问题起因查找,BUG修复; 7、有以下调试工具应用教训的:spx++,bugtrap,crashreport,log4plus,gflags,bondcheck,有逆向工程ollydbg等调试的优先。 本科或以上学历,计算机、通信相干业余优先; 1年以上 C++ / Qt开发教训; ...

October 31, 2020 · 2 min · jiezi

关于c++:谈谈如何学习Linux内核

学习内核的益处很多,在学习过程中不仅能够夯实大量实践根底,还能够学习到很多编码习用法,晋升学习能力和剖析能力。 一、确立高度,明确指标 高度决定视角,视角决定口头在学习内核过程中最容易犯的谬误,也是十分难把握的其实是你站在一个什么样的高度下来学习。站什么样的高度去学习也与本身的能力相干,所以这个问题其实更多是在新开始学习的学习者感到十分苦楚的一件事。一方面又心愿本人能学懂,然而又不晓得如何开始动手。 我列举几个常见的例子: (1) 一开始就看源码,最开始我也做过这种事,内核有什么都不晓得,后果就想着啃0.11的内核,后果很显然,2天立马放弃,齐全看不懂。 (2) 翻开书从第一页开始往下啃,如果这本书比拟薄还好,如果比拟厚,比方《深刻Linux内核架构》,那看2天也得放弃。 (3) 不喜爱看目录,不喜爱疾速浏览,就想着一个一个字眼的往下抠。如果自身有肯定根底,看的时候还不会感觉腻,然而很快就发现,看了半天,什么都没有记住。 还有很多相似的问题,这些都是咱们平时学习的时候特地容易呈现的一些误区。这些其实都是没有正确扫视本人的能力,胡乱筛选高度导致。 高度是什么?高度越高,也就是越偏差于了解各种抽象概念,偏向于构建对整体构造的一个认知,疏忽一些不必要细节,不关怀技术实现伎俩。高度越低,也就是越偏差于对应用技术的抉择,偏向于代码实现的各个细节,然而前提个别会在某个形象的概念畛域内进行各种细节性的探讨。 咱们的大脑更偏向于了解形象的内容,然而在口头时,咱们却更偏向于去把握细节性的内容。后果导致的内容就是,咱们总是心愿通过学习细节来结构对抽象概念的了解,最初被细节性内容中各种噪声烦扰思路,产生一种“这货色好难”的错觉。在了解了这点,那高度对咱们的行为有和指导意义也就跃然纸上了?以读书为例。站的越高,意味着本人看的内容越毛糙,也就是看书的时候不会去逐字逐句的看,而是一个章节一个章节的看,极其的状况就是只看目录,在这个过程中次要集中精力构建整体构造,对外围的概念进行形象。这时候学的内容都绝对外表,然而益处就是对当前的学习有很强的指导意义,毛病很显著,会让人底气不足,而且在达到肯定水平后,很容易达到瓶颈,察觉怎么看都看不懂了。站的越低,意味着本人看的内容很粗疏,看书的时候就是一个个字眼的扣,极其状况就是开始浏览源码,去看开源社区的各种问题。然而就像诗句说的,站的越低,也就常有一种“不识庐山真面目,只缘身在此山中”的感觉。这种状况下特地容易被各种细节烦扰,例如为什么要有这些参数,为什么这里须要判断这个条件等等这些细枝末节的问题。 如何使用高度以前对一篇博文印象很粗浅,作者了解的学习曲线划分成了两个比拟大的过程,回升的过程就是一个一直学习积攒的过程,而平缓没有增长的过程则是对之前积攒到饱和的常识进行消化的过程。我将这个学习过程进行进一步的划分,我感觉在学习积攒的前半部分应该以偏差学习抽象概念为主,而后半局部应该偏差学习实现细节。 所以集体的心得是从高到低的学习,在一个新的学习阶段,应该先多花点工夫学习一些概念化的内容,这时候切忌去看具体的实现,而是多思考如何在大脑中构建各种形象模型 对整体的架构有所概念了,而后开始学习一些细节性的内容,比方开始看些源码,抠写书上的字眼,读读一些具体的博客什么的。 二、学习小Tips 1.如何看书不要从第一页开始翻 不要一页一页的翻 花些工夫看看前言,在很多书的前言局部,作者会通知你,整本书的构造应该是什么样,应该要以什么样的程序去浏览,在浏览的时候应该站在什么样的角度去浏览,这是作者的倡议,有什么比作者的倡议更值得咱们听取呢!?不要寄心愿与一次看懂一本书,越是好的书越是要重复的看,然而很多人对这个重复了解有问题,认为重复的看就是一页页翻,反复看几遍。其实不是这样,每次重复应该让本人换一个高度,第一次翻的时候能够站在很高的高度,看一本书甚至只须要1天的工夫,反复几次后,站的高度应该越低,很可能看一个章节须要1天工夫,甚至有时候看一页就须要1天的工夫。一本书的目录就像你在沙漠中的指南针,不要疏忽目录的作用。每次翻开书,在决定本人看什么之前,花点工夫浏览下目录,让本人回顾(理解)要看的章节的架构,带着这个构造去学习事倍功半。带着问题去看书,这点很难,因为提什么样的问题和你抉择的高度密切相关,站的高度越高,那就越不要给本人提一些细节性的问题,反之则反之。2.如何看代码如果开始看代码,肯定要记住,本人曾经站在一个十分底层的高度度了,可能有能力浏览代码,就意味着你必须对整体的构造有比拟清晰的意识,如果你都不晓得这个构造,那看代码为时太早。 无论是什么样的代码,其实思路都很相似,即便Linux内核是用C这种面相过程的语言编写,然而这么多年倒退下来,Linux内核曾经带有了大量面对对象编程的特点。 在看代码的时候也是有两种不同的高度能够抉择,我先解释其中最粗疏的一种: (1)如何浏览函数一个函数写下来常常上百行,然而你须要一行一行的看么?必定不能,那清晰意识一个函数的构造就很重要。 一个函数就是为了解决一个问题,函数名根本都能阐明其性能,函数参数是输出,返回值就是输入,函数体就是整体的执行逻辑。在函数体外部,也根本都是相似的逻辑,先是对各种输出参数进行查看,而后书写性能逻辑,而后结构输入的后果。所以一个函数写下来总是这样的一种构造。 输入后果 函数名(输出){if (输出的参数有问题){异样解决,跳出}筹备参数 性能逻辑 结构输入后果 返回输入后果} 一个函数其实就是一个办法,浏览的难度比书写的难度要低,书写代码须要思考的问题十分多,然而在浏览代码的时候问题就简略很多,很多书写代码过程中须要思考的问题在浏览代码的过程中就不须要思考 。 函数名:在书写代码过程中须要思考一个函数的函数名须要可能准确表白出这个函数所具备的性能,所以常常存在各种名目标准。而浏览代码过程则能够通过浏览函数名大抵理解这个函数的性能。正文:在编写代码的时候,都会倡议增加对应的函数正文,解释函数体的性能和一些注意事项;在浏览过程中能够选择性的浏览这些正文(留神:是选择性浏览,千万不要每个正文都读)输出参数:在书写代码的时候,这部分的内容也是很头疼的内容,不仅须要确定须要哪些输出,还须要输出的模式,而且还须要准确定义每个输出参数的语义;然而在浏览代码的过程中,这部分内容根本能够疏忽,咱们很少会关系所看到的函数须要哪些参数输出。输入后果:在书写代码的时候,这部分也是很头疼的一件事,因为准确定义输入后果也是十分艰难和麻烦的一件事;在浏览代码过程中,也须要留神输入后果,不然一个函数执行了老半天,后果连输入后果是什么都没概念,也太失败了点。参数检测:在编写代码过着中十分烦的一件事,每个人都心愿调用函数的人会传入正确的参数,然而基本做不到,后果每次都要花费肯定精力对输出参数的边界、非空等进行查看;在浏览代码过程中,基本不须要浏览这部分的代码,恰好这部分内容在每个函数体中占据了相当一部分的地位;参数筹备:编写代码的过程中,因为函数体外部的逻辑须要进行很多筹备,所以经常须要有一个参数筹备的过程;而浏览代码的过程根本能够疏忽这部分的逻辑,或者疾速浏览这部分逻辑,这里恰好是很多老手破费大量精力纠缠的内容,其实没必要在这里纠结,跳过就好。性能逻辑:这部分是函数体中最为精髓的局部,而且代码编写起来也是相当的麻烦,被各种逻辑弄的死去火来,最初还须要重构等等伎俩;在浏览代码过程中,这部分其实很难把握,因为性能逻辑可能被封装在另外一个函数外部,这时候大家会习惯性的持续深刻看,后果弄的本人更加凌乱,又比方有的时候几个性能逻辑点组成了一套逻辑,然而大家却将这部分逻辑割裂来看,后果总感觉读的很顺当。这部分内容须要一些教训,然而有一个领导,就是在看这部分代码的时候要留神本人所站的高度,抉择采纳何种策略。结构输入后果:函数体外部还会破费大量的代码进行对最初返回后果的结构工作,就像搭积木一样;不过在浏览代码的时候,咱们并不需要破费太多精力在这些逻辑上,多留神留神一些返回后果的语义。浏览代码还有很多技巧,例如如何在带有goto语句的代码中疾速了解逻辑,如何界定那些正文是能够疏忽的,如何将一些代码逻辑看成一块整体内容,何时应该跳到更深的一层函数浏览等等。这些都须要平时的教训积攒。 (2)如何在大量的代码中熟能生巧看代码有一个粒度问题,咱们不能一行一行的看,也不能一个一个函数的看,我之前提到了,Linux内核有大量面向对象编程的影子,所以在看大量代码的时候,必须学会面向对象编程的思维模式。这样对本人在大量代码浏览中提供大量参考意见。 或者有人会通知你,面向对象编程就是弄明确什么是对象、如何写一个class就能够了。的确,学习面向对象编程,弄明确对象是根底,不过我感觉能够再拔高一点,了解一些更形象的概念,在这些抽象概念的领导上来学习,能够有更多的指导意义。 层:层并不是面向对象编程特有,然而了解层是很重要的,咱们遇到的典型的层就是网络协议栈,为什么咱们网络协议会有那么多层,就因为须要解决的事件太多,咱们不得不将内容一块块的宰割,宰割的时候,发现用层进行组织,能够让构造更加清晰,所以你当前会发现,大量的零碎都会带有层的滋味。linux内核中带有大量的层设计,如网络协议栈有层,内存治理与寻址有层,文件I/O也有层。畛域模型:畛域模型就是一个零碎中最为外围的几个形象实体,一个零碎,根本就是围绕着畛域模型开展,在学习内核不同的子系统的时候,肯定要花大量的精力在畛域模型上,切记!!!在Linux内核上也有大量的畛域模型,例如在虚构文件系统局部存在4大形象inode,dentry,file等。在过程调度零碎的最外围形象是task_struct。在过程地址空间则有mm_struct,address_space等这些外围的畛域模型。我感觉能够破费80%的工夫在了解这些畛域模型上。畛域驱动类:畛域模型外部其实是大量的属性组成,然而如果只有属性,没有一个执行的办法,那这个畛域模型也不能发挥作用,面向对象编程的做法就是将这些办法编程畛域驱动类,说的直白一些就是接口。在Linux中就是那些函数指针和对应的回调函数。平时看代码,大家会破费大量的工夫去看各个回调函数,这个其实是吃力不讨好的方法,与其花大量的心理去看各个回调函数的实现,不如多思考下,为什么会有这些操作方法,它们是如何形象进去的。如果可能了解上述的这几个形象,那在大量代码中如何熟能生巧就绝对容易了,有一个简略的套路:(1) 在较高的角度,弄明确一个零碎为了解决什么问题,应该有哪些形象 (2) 在对整体构造有所理解当前,花心思看看这些形象对应的畛域模型,因为个别状况畛域模型很宏大,所以看的时候也须要有步骤的进行拆解学习。 (3) 在对畛域模型有所理解后,开始看畛域驱动类,想明确为什么会有这些操作。 (4) 在上述筹备好后,就能够破费一些工夫去看各个函数的具体实现,并且在看的过程中多思考畛域模型为什么这么设计。

October 30, 2020 · 1 min · jiezi

关于c++:题解洛谷-P1598-垂直柱状图

洛谷 P1598 垂直柱状图思路用大小为26的数组存储每个字母呈现的次数。先用Max求出呈现次数最多的字母的呈现次数。而后每次遍历,如果该字母呈现次数>=Max,则输入'*';否则输入' '。最初一行原样输入就行。 代码#include <bits/stdc++.h>using namespace std;int main() { freopen("in.txt", "r", stdin); ios::sync_with_stdio(false); cin.tie(nullptr); string s; int n = 4; int arr[26] = {0}; while (n--) { getline(cin, s); for (char i : s) { if (i >= 'A' && i <= 'Z') { arr[i - 'A']++; } } } int Max = 0; for (int i : arr) { if (i > Max) { Max = i; } } while (Max > 0) { for (int i = 0; i < 25; i++) { if (arr[i] >= Max) { cout << "* "; } else { cout << " "; } } if (arr[25] >= Max) { cout << "*" << endl; } else { cout << " " << endl; } Max--; } cout << "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"; return 0;}

October 30, 2020 · 1 min · jiezi

关于c++:linux下定位多线程内存越界问题实践总结

最近定位了在一个多线程服务器程序(OceanBase MergeServer)中,一个线程非法篡改另一个线程的内存而导致程序core掉的问题。定位这个问题历经波折,尝试了各种内存调试的方法。往往感觉就要柳暗花明了,却发现又进入了另一个死胡同。最初,应用弱小的mprotect+backtrace+libsigsegv等工具胜利定位了问题。整个定位过程遇到的问题和解决办法对于多线程内存越界问题都很典型,简略总结一下和大家分享。 景象core是在系统集成测试过程中发现的。服务器程序MergeServer有一个50个工作线程组成的线程池,当应用8个线程的测试程序通过MergeServer读取数据时,后者偶然会core掉。用gdb查看core文件,发现core的起因是一个指针的地址非法,当过程拜访指针指向的地址时引起了段谬误(segment fault)。见下图。 产生越界的指针ptr_位于一个叫做cname_的对象中,而这个对象是一个动静数组field_columns_的第10个元素的成员。如下图。 复现问题之后,花了2天的工夫,终于找到了重现问题的办法。重现屡次,能够察看到如下一些景象: 随着客户端并发数的加大(从8个线程到16个线程),出core的概率加大;缩小服务器端线程池中的线程数(从50个到2个),就不能复现core了。被篡改的那个指针,总是有一半(高4字节)被改为了0,而另一半看起来仿佛是正确的。请看前一节,重现屡次,每次出core,都是因为field_columns_这个动静数组的第10个元素data_[9]的cname_成员的ptr_成员被篡改。这是一个不好解释的奇怪景象。在代码中插入检查点,从field_columns_中内容最后产生到读取导致越界的这段代码序列中“埋点”,既应用二分查找法定位篡改cname_的代码地位。后果发现,程序有时core到检查点前,有时又core到检查点后。综合以上景象,初步判断这是一个多线程程序中内存越界的问题。 应用glibc的MALLOC_CHECK_因为是一个内存问题,思考应用一些内存调试工具来定位问题。因为OB外部对于内存块有本人的缓存,须要去除它的影响。批改OB内存分配器,让它每次都间接调用c库的malloc和free等,不做缓存。而后,能够应用glibc内置的内存块完整性检查性能。 应用这一个性,程序无需从新编译,只须要在运行的时候设置环境变量MALLOC_CHECK_(留神结尾的下划线)。每当在程序运行过程free内存给glibc时,glibc会查看其暗藏的元数据的完整性,如果发现错误就会立刻abort。用相似上面的命令行启动server程序: export MALLOC_CHECK_=2bin/mergeserver -z 45447 -r 10.232.36.183:45401 -p45441应用MALLOC_CHECK_当前,程序core到了不同的地位,是在调用free时,glibc查看内存块后面的校验头谬误而abort掉了。如下图。 但这个core能带给咱们想信息也很少。咱们只是找到了另外一种稍高效地重现问题的办法而已。或者最后看到的core的景象是延后浮现而已,其实“更早”的时刻内存就被毁坏掉了。 valgrindglibc提供的MALLOC_CHECK_性能太简略了,有没有更高级点的工具不光可能报告谬误,还能剖析出问题起因来?咱们天然想到了赫赫有名的valgrind。用valgrind来查看内存问题,程序也不须要从新编译,只须要应用valgrind来启动: nohup valgrind --error-limit=no --suppressions=suppress bin/mergeserver -z 45447 -r 10.232.36.183:45401 -p45441 >nohup.out &默认状况下,当valgrind发现了1000中不同的谬误,或者总数超过1000万次谬误后,会进行报告谬误。加了--error-limit=no当前能够禁止这一个性。--suppressions用来屏蔽掉一些不关怀的误报的问题。通过一翻折腾,用valgrind复现不了core的问题。valgrind报出的谬误也都是一些与问题无关的误报。大略是因为valgrind运行程序大概会使程序性能慢10倍以上,这会影响多线程程序运行时的时序,导致core不能复现。此路不通。 须要C/C++ Linux高级服务器架构师学习材料后盾加群812855908(包含C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等) magic number既然MALLOC_CHECK_能够检测到程序的内存问题,咱们其实想晓得的是谁(哪段代码)越了界。此时,咱们想到了应用magic number填充来标示数据结构的办法。如果咱们在被越界的内存中看到了某个magic number,就晓得是哪段代码的问题了。 首先,批改对于malloc的封装函数,把返回给用户的内存块填充为非凡的值(这里为0xEF),并且在开始和完结局部各多申请24字节,也填充为非凡值(起始0xBA,结尾0xDC)。另外,咱们把预留内存块头部的第二个8字节用来存储以后线程的ID,这样一旦察看到被越界,咱们能够据此断定是哪个线程越的界。代码示例如下。 而后,在用户程序通过咱们的free入口开释内存时,对咱们填充到边界的magic number进行查看。同时调用mprobe强制glibc对内存块进行完整性检查。 最初,给程序中所有被狐疑的要害数据结构加上magic number,以便在调试器中查看内存时能辨认进去。例如 好了,都加好了。用MALLOC_CHECK_的形式从新运行。程序如咱们所愿又core掉了,查看被越界地位的内存: 如上图,红色局部是咱们本人填充的越界查看头部,能够看到它没有被毁坏。其中第二行存储的线程号通过确认的确等于咱们以后线程的线程号。 蓝色局部为前一个动态内存调配的结尾,也是残缺的(24个字节0xdc)。0x44afb60和0x44afb68两行所示的内存为glibc malloc存储本身元数据的中央,程序core掉的起因是它查看这两行内容的完整性时发现了谬误。由此推断,被非法篡改的内容小于16个字节。仔细观察这16字节的内容,咱们没有看到相熟的magic number,也就无奈推知有bug的代码是哪块。这和咱们最后发现的core的景象互相印证,很可能被非法批改的内容仅为4个字节(int32_t大小)。 另外,尽管咱们加宽了查看边界,程序还是会core到glibc malloc的元数据处,而不是咱们增加的边界里。而且,咱们总能够察看到前一块内存(图中蓝色所示)的结尾时残缺的,没被毁坏。这阐明,这不是简略的内存拜访超出边界导致的越界。咱们能够大胆的做一下猜想:要么是一块曾经开释的内存被非法重用了;要么这是通过野指针“空投”过去的一次内存批改。 如果咱们的猜想是正确的,那么咱们用这种增加内存边界的形式查看内存问题的办法简直必然是有效的。 打怪利器electric-fence至此,咱们晓得某个时间段内某个变量的内存被其余线程非法批改了,然而却无奈定位到是哪个线程哪段代码。这就好比你明明晓得将来某个时间段在某个地点会产生凶案,却没方法看到凶手。无比郁闷。 有没有方法能检测到一个内存地址被非法写入呢?有。又一个赫赫有名的内存调试库electric-fence(简称efence)就富丽退场了。 应用MALLOC_CHECK_或者magic number的形式检测的最大问题是,这种查看是“预先”的。在多线程的简单环境中,如果不能产生毁坏的第一工夫查看现场,往往曾经不能发现罪魁祸首的蛛丝马迹了。 electric-fence利用底层硬件(CPU提供的虚拟内存治理)提供的机制,对内存区域进行爱护。实际上它就是应用了下一节咱们要本人编码应用的mprotect零碎调用。当被爱护的内存被批改时,程序会立刻core掉,通过查看core文件的backtrace,就容易定位到问题代码。 这个库的版本有点凌乱,容易弄错。搜寻和下载这个库时,我才发现,electric-fence的作者也是赫赫有名的busybox的作者,牛人一枚。然而,这个版本在linux上编译连贯到我的程序的时候会报WARNING,而且前面执行的时候也会出错。起初,找到了debian提供的一个更高版本的库,预计是社区针对linux做了改良。 应用efence须要从新编译程序。efence编译后提供了一个动态库libefence.a,它蕴含了可能代替glibc的malloc, free等库函数的一组实现。编译时须要一些技巧。首先,要把-lefence放到编译命令行其余库之前;其次,用-umalloc强制g++从libefence中查找malloc等原本在glibc中蕴含的库函数: g++ -umalloc –lefence …用strings来查看产生的程序是否真的应用了efence: 和很多工具相似,efence也通过设置环境变量来批改它运行时的行为。通常,efence在每个内存块的结尾搁置一个不可拜访的页,当程序越界拜访内存块前面的内存时,就会被检测到。如果设置EF_PROTECT_BELOW=1,则是在内存块前插入一个不可拜访的页。通常状况下,efence只检测被调配进来的内存块,一个块被调配进来后free当前会缓存下来,直到一下次调配进来才会再次被检测。而如果设置了EF_PROTECT_FREE=1,所有被free的内存都不会被再次调配进来,efence会检测这些被开释的内存是否被非法应用(这正是咱们目前狐疑的中央)。但因为不重用内存,内存可能会收缩地很厉害。 我应用下面2个标记的4种组合运行咱们的程序,遗憾的是,问题无奈复现,efence没有报错。另外,当EF_PROTECT_FREE=1时,运行一段时间后,MergeServer的虚拟内存很快收缩到140多G,导致无奈持续测试上来。又进入了一个死胡同。 终极神器mprotect + backtrace + libsigsegvelectric-fence的神奇能力实际上是应用零碎调用mprotect实现的。mprotect的原型很简略, int mprotect(const void *addr, size_t len, int prot);mprotect能够使得[addr,addr+len-1]这段内存变成不可读写,只读,可读写等模式,如果产生了非法拜访,程序会收到段谬误信号SIGSEGV。 但mprotect有一个很强的限度,要求addr是页对齐的,否则零碎调用返回谬误EINVAL。这个限度和操作系统内核的页管理机制相干。 如图,咱们曾经晓得这个动静数组的第10个元素会被非法越界批改。review了代码,发现从这个数组内容初始化结束当前,到应用这个数组内容这段时间,不应该再有批改操作。那么,咱们就能够在数组内容被初始化之后,立刻调用mprotect对其进行只读爱护。 尝试一因为mprotect要求输出的内存地址页对齐,所以我批改了动静数组的实现,每次申请内存块的时候多调配一个页大小,而后取页对齐的地址为第一个元素的起始地位。 如上图,浅蓝色局部为为了对齐内存地址而做的padding。代码见下 ...

October 30, 2020 · 1 min · jiezi

关于c++:2021年Linux服务器开发的知识技术合集基础入门到高级进阶

前言本文介绍下Linux从入门到高级进阶的学习路线。 整个路线体系专一于服务器后盾开发,知识点包含C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等等 (技术点目尾都提供免费视频,关注+qun832218493取材料) 资源列表:1:linux零根底入门 2:linux服务器开发 3:架构师开发 4:linux内核 5:webrtc入门到精通 6:音视频FFmpeg 7:神器Git入门到精通 什么是Linux?Linux是一个操作系统软件。与Windows不同的是,Linux是一套凋谢源代码程序的、并能够自在流传的类Unix操作系统,它是一个反对多用户、多任务、多线程和多CPU的操作系统。它能运行次要的UNIX工具软件、应用程序和网络协议。它反对32位和64位硬件。 Linux继承了Unix以网络为外围的设计思维,是一个性能稳固的多用户网络操作系统。 linux零根底入门:如何疾速入门,须要哪些知识点?1:linux环境专栏 linux零碎装置 linux开发环境ssh与Samba配置 linux开发环境Gcc配置 linux的命令操作8条目录操作与5条文件操作 2:shell 脚本编程案例 3:统计文件单词数量(文本操作) 状态机实现文件单词统计 4:实现通讯录(构造体) 通讯录实现的架构设计与需要剖析 链表的实现与数据结构的定义 架构接口层的实现 业务逻辑的剖析与实现 通讯录人员操作代码的调试 通讯录人员操作代码调试与运行 通讯录删除人员操作的调试与BUG解决 文件保留于加载的接口层实现 文件保留业务实现 通讯录调试与运行 5:并发下的技术计划(锁) 多线程并发锁的我的项目介绍 多线程并发锁的计划一互斥锁 多线程并发锁的计划一自旋锁 多线程并发锁的计划一原子操作 附: linux服务器开发Linux后端服务器开发是针对有Linux根底的,想从事Linux后端服务器开发的。 Linux后端服务器开发一起是由八个维度所组成, 具体知识点: 1. 算法与设计专题千里之行,始于足下。不积跬步,无以至千里。既能俯视星空又能好高鹜远。 排序与查找 插入排序 疾速排序 希尔排序 桶排序 基数排序 归并排序 罕用算法 布隆过滤器 字符串匹配 KMP算法 回溯算法 贪婪算法 举荐算法 深度优先,广度优先 罕用的数据结构 均衡二叉树 红黑树 B-树 KMP算法 栈/队列 布隆过滤器 ...

October 29, 2020 · 5 min · jiezi

关于c++:cc后台开发必知堆与栈的区别

堆(Heap)与栈(Stack)是开发人员必须面对的两个概念,在了解这两个概念时,须要放到具体的场景下,因为不同场景下,堆与栈代表不同的含意。个别状况下,有两层含意:(1)程序内存布局场景下,堆与栈示意两种内存治理形式;(2)数据结构场景下,堆与栈示意两种罕用的数据结构。 1.程序内存分区中的堆与栈1.1 栈简介栈由操作系统主动调配开释 ,用于寄存函数的参数值、局部变量等,其操作形式相似于数据结构中的栈。参考如下代码: int main() { int b; //栈 char s[] = "abc"; //栈 char *p2; //栈}其中函数中定义的局部变量依照先后定义的程序顺次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。栈的内存地址成长方向与堆相同,由高到底,所以后定义的变量地址低于先定义的变量,比方下面代码中变量 s 的地址小于变量 b 的地址,p2 地址小于 s 的地址。栈中存储的数据的生命周期随着函数的执行实现而完结。 1.2 堆简介堆由开发人员调配和开释, 若开发人员不开释,程序完结时由 OS 回收,调配形式相似于链表。参考如下代码: int main() { // C 中用 malloc() 函数申请 char* p1 = (char *)malloc(10); cout<<(int*)p1<<endl; //输入:00000000003BA0C0 // 用 free() 函数开释 free(p1); // C++ 中用 new 运算符申请 char* p2 = new char[10]; cout << (int*)p2 << endl; //输入:00000000003BA0C0 // 用 delete 运算符开释 delete[] p2;}其中 p1 所指的 10 字节的内存空间与 p2 所指的 10 字节内存空间都是存在于堆。堆的内存地址成长方向与栈相同,由低到高,但须要留神的是,后申请的内存空间并不一定在先申请的内存空间的前面,即 p2 指向的地址并不一定大于 p1 所指向的内存地址,起因是先申请的内存空间一旦被开释,后申请的内存空间则会利用先前被开释的内存,从而导致先后调配的内存空间在地址上不存在先后关系。堆中存储的数据若未开释,则其生命周期等同于程序的生命周期。 ...

October 26, 2020 · 3 min · jiezi

关于c++:题解洛谷-P1553-数字反转升级版

洛谷 P1553 数字反转(升级版)题目链接 思路模拟题,采纳字符串输出,通过查找字符串中是否含有'/''.''%'字符,来分类解决。 代码/* * @Description: * @Author: 多多 * @Date: 2020-10-26 10:01:01 * @LastEditTime: 2020-10-26 12:06:27 * @LastEditors: 多多 */#include <bits/stdc++.h>using namespace std;int main(){ freopen("./INPUT/P1553.in", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); string s; cin >> s; if (s.find('.') != string::npos) { int index = s.find('.'); reverse(s.begin(), s.begin() + index); reverse(s.begin() + index + 1, s.end()); while (s[0] == '0' && s[1] != '.') { s.erase(0, 1); } while (s[s.length() - 1] == '0' && s[s.length() - 2] != '.') { s.erase(s.length() - 1, 1); } } else if (s.find('/') != string::npos) { int index = s.find('/'); reverse(s.begin(), s.begin() + index); reverse(s.begin() + index + 1, s.end()); while (s[0] == '0' && s[1] != '/') { s.erase(0, 1); } index = s.find('/'); while (s[index + 1] == '0') { s.erase(index + 1, 1); } } else if (s.find('%') != string::npos) { reverse(s.begin(), s.end() - 1); while (s[0] == '0' && s.length() != 2) { s.erase(0, 1); } } else { reverse(s.begin(), s.end()); while (s[0] == '0' && s.length() != 1) { s.erase(0, 1); } } cout << s << endl; return 0;}

October 26, 2020 · 1 min · jiezi

关于c++:题解洛谷-P1308-统计单词数

洛谷 P1308 统计单词数思路一开始,我的想法是不一次性读取第二行整行的字符串,二是一个单词一个单词地输出,再与第一行的字符串作比拟,然而提交代码之后发现了问题:如果第二行字符串的结尾是空格,就会出错。 错误代码/* * @Description: * @Author: 多多 * @Date: 2020-10-25 17:35:26 * @LastEditTime: 2020-10-26 07:33:38 * @LastEditors: 多多 */#include <bits/stdc++.h>using namespace std;int main(){ freopen("./INPUT/P1308.in", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); string s1, s2; cin >> s1; transform(s1.begin(), s1.end(), s1.begin(), ::tolower); bool bo = true; int pos = -1; int len_sum = 0; int sum = 0; while (cin >> s2) { transform(s2.begin(), s2.end(), s2.begin(), ::tolower); if (s1 == s2) { if (bo) { pos = len_sum; bo = false; } sum++; } len_sum += s2.length() + 1; } if (bo) { cout << -1 << endl; } else { cout << sum << " " << pos << endl; } return 0;}接下来的思路还是中规中矩一次性读入第二行字符串,再做子串匹配。 ...

October 26, 2020 · 2 min · jiezi

关于c++:读数据密集型应用系统设计有感而发二数据存储与检索

如果你把货色整顿得东倒西歪,下次就不必查找了 --------德国谚语 从最根本的层面上看,数据库只须要做两件事:向它插入数据时,它就保留数据;之后查问时他就返回数据。接下来也就围绕着查问和存储这两个话题开展,存储时有两种比拟罕用的数据结构LSM和B-Tree,基于数据的查问依据不同的利用场景能够分为两种形式事务处理(OLTP)和剖析解决(OLAP)。 LSM数据结构 LSM数据结构晚期是利用于日志构造文件系统上的,是一种基于合并和压缩的排序文件索引的存储引擎,在leveldb,rocksdb等存储系统上有宽泛的利用。 它是以一种程序写的形式将值写磁盘,相比于随机写速度上有大大的晋升。对于写入的数据在磁盘上保障程序性,键值能够采纳稠密的形式存储在内存,查问时能够定位数据的范畴,在节俭内存的同时放慢查问的速度。当插入的数据达到一定量时,对数据块进行合并压缩解决。 1.文件格式 二进制的形式进行存储。 2.删除记录 不间接删除数据,而是采纳标记位的形式示意已删除,在合并的时候抛弃。 3.解体复原 对于写入内存的数据通过追加磁盘日志的形式备份,能够及时复原。 4.局部写入的记录 减少校验位解决,对于不残缺的数据抛弃。 5.并发管制 因为是程序写的形式,以一个线程写,多个线程读的形式来实现并发。 6.保障磁盘数据程序性 能够采纳跳表,红黑树等数据结构实现 7.对于不存在的数据晋升查问性能 能够采纳布隆过滤器的形式 B-Tree数据结构 B-Tree是目前宽泛应用且比拟成熟的数据库底层存储构造,mysql就是采纳该数据结构实现的。B-tree将数据库分解成大小固定的块或页,通常为4KB,相似于底层磁盘的块排列形式,能够让一个页面援用另一页面,结构一个树状页面。数据是以程序的形式排列,插入时须要找到键的地位,如果此时改块已满须要进行决裂操作。 1.可靠性通过预写日志(WAL)的形式存储数据库的操作,避免零碎解体时数据失落。 2.节俭内存保留键的缩略信息,而不是残缺的键,这样能够节俭空间。 3.大范畴查问相邻的页在磁盘中顺序存储,缩小磁盘IO 4.查问速度能够减少兄弟指针,这样能够不必返回父指针再拜访一次 5.LSM和B-Tree比照LSM整体的写性能比B-Tree好,数据的压缩性能更好。B-Tree整体的读性能更加优异,且在合并压缩这块不须要耗费更多的性能,反对事务语义。须要依据理论利用的场景,抉择相应的数据结构。 事务处理与剖析解决在线事务处理指的是日常程序中的增删改查操作,在线剖析解决次要是预先对数据分析,波及数据量较大,且个别读取的是某几列的值。 属性事务处理零碎剖析零碎次要读特色基于键,每次查问返回大量的记录对大量记录进行汇总次要写特色随机拜访,低提早写入用户的输出批量导入或事件流典型应用场景终端用户,通过网络应用程序外部分析师,为决策提供反对数据表征最新的数据状态随着工夫而变动的所有事件历史数据规模GB到TBTB到PB列式存储如果事实表中无数以万亿行,PB大小的数据,则高效地存储和查问这些数据将成为一个具备挑战性的问题。面向列存储的想法很简略:不要将一行的所有值存储在一起,而是将每列的所欲值存储在一起。列式存储能够不便数据的压缩,能够节俭存储空间。 作为利用开发人员,把握更多无关存储引擎外部的常识,能够更好地理解哪种工具最适宜你的具体利用。

October 25, 2020 · 1 min · jiezi

关于c++:题解洛谷-P5734-深基6例6文字处理软件

洛谷 P5734 【深基6.例6】文字处理软件思路简略的字符串操作,其中字符串查找,s.find()函数,判断是否找到要用if (s.find()!=string::npos)来判断 代码/* * @Description: * @Author: 多多 * @Date: 2020-10-25 08:40:40 * @LastEditTime: 2020-10-25 09:00:40 * @LastEditors: 多多 */#include <bits/stdc++.h>using namespace std;int main(){ freopen("./INPUT/P5734.in", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; string s = ""; cin >> s; while (n--) { int x; cin >> x; if (x == 1) { string ss; cin >> ss; s += ss; cout << s << endl; } else if (x == 2) { int a, b; cin >> a >> b; s = s.substr(a, b); cout << s << endl; } else if (x == 3) { int a; string ss; cin >> a >> ss; s.insert(a, ss); cout << s << endl; } else if (x == 4) { string ss; cin >> ss; if (s.find(ss) != string::npos) { cout << s.find(ss) << endl; } else { cout << -1 << endl; } } } return 0;}

October 25, 2020 · 1 min · jiezi

关于c++:题解洛谷-P5015-标题统计

洛谷 P5015 题目统计水题代码/* * @Description: * @Author: 多多 * @Date: 2020-10-24 22:51:24 * @LastEditTime: 2020-10-24 22:53:02 * @LastEditors: 多多 */#include <bits/stdc++.h>using namespace std;int main(){ freopen64("P5015.in", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); string s; int sum = 0; while (cin >> s) { sum += s.length(); } cout << sum << endl; return 0;}

October 24, 2020 · 1 min · jiezi

关于c++:题解洛谷-P3741-honoka的键盘

洛谷 P3741 honoka的键盘题目链接 思路题中无非三种状况: VK,间接计数VV,扭转一个字符后计数KK,扭转一个字符后计数KV,无论如何无奈计数能够先遍历一遍,把所有VK找进去,计数,而后把VK换成“XX”,再进行第二次遍历,找VV或者KK,如果找到,总数就加1,并退出循环。 代码/* * @Description: * @Author: 多多 * @Date: 2020-10-24 22:28:12 * @LastEditTime: 2020-10-24 22:32:09 * @LastEditors: 多多 */#include <bits/stdc++.h>using namespace std;int main(){ //freopen("P3741.in", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; string s; cin >> s; int sum = 0; for (int i = 0; i < n - 1; i++) { if (s[i] == 'V' && s[i + 1] == 'K') { sum++; s[i] = s[i + 1] = 'X'; } } for (int i = 0; i < n - 1; i++) { if ((s[i] == 'V' && s[i + 1] == 'V') || (s[i] == 'K' && s[i + 1] == 'K')) { sum++; break; } } cout << sum << endl; return 0;}

October 24, 2020 · 1 min · jiezi

关于c++:c-通过-libraw-获取-raw-格式的-rgb-值

概述获取 canon CR2 格局的 rgb 值,因为 opencv 的 imread 并不反对 CR2 格局的,所以先用 libraw 解决,而后转成 Mat 矩阵解决,最初再通过 opencv 获取 rgb 的值。 步骤1. 初始化 libraw libraw_data_t *iprc = libraw_init(0);2. 关上 CR2 文件 QString imgSavePath("C://Users//Administrator//Desktop//test//IMG_0782.CR2"); ret = libraw_open_file(iprc,imgSavePath.toStdString().data());3. 解包 raw 的原始格局 libraw_unpack(iprc);4. 以 RGB 位图模式存储到缓存 int check = libraw_dcraw_process(iprc); // 模仿 dcraw 解决 libraw_processed_image_t* img = libraw_dcraw_make_mem_image(iprc, &check);5. 应用 Mat 结构获取到的数据 cv::Mat output = cv::Mat(cv::Size(img ->width, img ->height), CV_16UC3, img ->data, cv::Mat::AUTO_STEP);6. 转成 IplImage 格局并将获取到的 rgb值写入到 txt 中 IplImage img = IplImage (output); CvScalar pixel; for (int i = 0; i < img.height; ++i) { for (int j = 0; j < img.width; ++j) { //取得像素的 RGB 值并显示 pixel = cvGet2D(&img, i, j); outfile << pixel.val[0] << "," << pixel.val[1] << "," << pixel.val[2]; outfile << "\n"; cvSet2D(&img, i, j, pixel); } }残缺代码int RawToRgb(){ int ret; QString imgSavePath("C://Users//Administrator//Desktop//test//IMG_0782.CR2"); libraw_data_t *iprc = libraw_init(0); libraw_output_params_t p = iprc->params; ret = libraw_open_file(iprc,imgSavePath.toStdString().data()); libraw_unpack(iprc); int check = libraw_dcraw_process(iprc); libraw_processed_image_t* img = libraw_dcraw_make_mem_image(iprc, &check); if(img != NULL) { ofstream outfile("C://Users//Administrator//Desktop//rgb.txt"); cv::Mat output = cv::Mat(cv::Size(img->width, img->height), CV_16UC3, img->data, cv::Mat::AUTO_STEP); IplImage rawImg = IplImage (output); // Mat 格局转为 IplImage 格局 CvScalar pixel; for (int i = 0; i < rawImg.height; ++i) { for (int j = 0; j < rawImg.width; ++j) { //取得像素的 RGB 值并显示,程序是 bgr pixel = cvGet2D(&rawImg, i, j); outfile << pixel.val[0] << "," << pixel.val[1] << "," << pixel.val[2]; outfile << "\n"; cvSet2D(&rawImg, i, j, pixel); } } } return 0;}参考资料libraw-docsrawpy-api

October 23, 2020 · 2 min · jiezi

关于c++:CC基础入门

1 C++初识1.1 第一个C++程序编写一个C++程序总共分为4个步骤 创立我的项目创立文件编写代码运行程序1.1.1 创立我的项目 Visual Studio是咱们用来编写C++程序的次要工具,咱们先将它关上 1.1.2 创立文件右键源文件,抉择增加->新建项 给C++文件起个名称,而后点击增加即可。 1.1.3 编写代码#include <iostream>using namespace std; //此行必不可少,如果省略则无奈间接应用cout,cin,endl,dec,hex,oct等等//#include编绎命令:将iostream文件的内容增加到程序中//iostream: io指输出和输入,应用cin和cout必须蕴含此文件//写完一个文件就Ctrl+A(全选) Ctrl+K+C(正文),要用的时候Ctrl+A而后Ctrl+K+U(勾销正文)int main(){ cout << "hello world" << endl; system("pause"); return 0;}1.1.4 运行程序 1.2 正文作用:在代码中加一些阐明和解释,不便本人或其余程序员程序员浏览代码 两种格局 单行正文:// 形容信息 通常放在一行代码的上方,或者一条语句的开端,==对该行代码阐明==多行正文: /* 形容信息 */ 通常放在一段代码的上方,==对该段代码做整体阐明==提醒:编译器在编译代码时,会疏忽正文的内容#include <iostream>using namespace std;//1. 单行正文//2. 多行正文 /* main是一个程序的入口 每个程序都必须有这么一个函数 但有且仅有一个 *///一个工作区不论几个我的项目,只能在一个时刻调试其中一个(有一个project 是active 的),只能有一个main函数在运行//要想同时运行多个cpp文件,能够将main更名即可int main(){ //在屏幕串输入hello world cout << "hello world" << endl; system("pause"); return 0;}1.3 变量作用:给一段指定的内存空间起名,不便操作这段内存 ...

October 23, 2020 · 23 min · jiezi

关于c++:连夜整理了28页C语言C常见面试题含答案

连夜整顿了68道C语言和C++相干的面试题,文末有PDF版具体答案,有须要的小伙伴们能够自取,面试前必看必背。 1 变量的申明和定义有什么区别2 简述#ifdef、#else、#endif和#ifndef的作用3 写出int 、bool、 float、指针变量与 “零值”比拟的if语句4 构造体能够间接赋值吗5sizeof和strlen的区别6 C 语言的关键字static和 C++ 的关键字static有什么区别7 C 语言的malloc和 C++ 中的new有什么区别8 写一个 “规范”宏MIN9 ++i和i++的区别10 volatile有什么作用11 一个参数能够既是const又是volatile吗12 a和&a有什么区别13 用 C 编写一个死循环程序14 构造体内存对齐问题15 全局变量和局部变量有什么区别?实怎么实现的?操作系统和编译器是怎么晓得的?16 简述 C、C++ 程序编译的内存分配情况17 简述strcpy、sprintf与memcpy的区别18 请解析(*(void (*)( ) )0)( )的含意19 C语言的指针和援用和c++的有什么区别?20 typedef和define有什么区别21 指针常量与常量指针区别22 简述队列和栈的异同23 设置地址为0x67a9的整型变量的值为0xaa6624 编码实现字符串转化为数字25 C 语言的构造体和 C++ 的有什么区别26 简述指针常量与常量指针的区别27 如何防止“野指针”28 句柄和指针的区别和分割是什么?29 new/delete与malloc/free的区别是什么30 说一说extern“C”31 请你来说一下 C++ 中struct和class的区别32 C++ 类内能够定义援用数据成员吗?33 C++ 中类成员的拜访权限34 什么是右值援用,跟左值又有什么区别?35 面向对象的三大特色36 说一说 c++ 中四种cast转换37 C++ 的空类有哪些成员函数38 对 c++ 中的smart pointer四个智能指针:shared_ptr,unique_ptr,weak_ptr,auto_ptr的了解39 说说强制类型转换运算符40 谈谈你对拷贝构造函数和赋值运算符的意识41 在 C++ 中,应用 malloc申请的内存是否通过delete开释?应用new申请的内存是否用free?42 用 C++ 设计一个不能被继承的类43 C++ 本人实现一个String类44 拜访基类的公有虚函数45 对虚函数和多态的了解46 简述类成员函数的重写、重载和暗藏的区别47 链表和数组有什么区别48 用两个栈实现一个队列的性能49 vector的底层原理50 vector中的reserve和resize的区别51 vector中的size和capacity的区别52 vector中erase办法与algorithn中的remove`办法区别53 vector迭代器生效的状况54 正确开释vector的内存(clear(), swap(), shrink_to_fit())55 list的底层原理56 什么状况下用vector,什么状况下用list,什么状况下用 deque57 priority_queue的底层原理58 map 、set、multiset、multimap的底层原理59 为何map和set的插入删除效率比其余序列容器高60 为何map和set每次Insert之后,以前保留的iterator不会生效?61 当数据元素增多时(从 10000 到 20000),map的set的查找速度会怎么变动?62 map 、set、multiset、multimap的特点63 为何map和set的插入删除效率比其余序列容器高,而且每次insert 之后,以前保留的iter64 为何map和set不能像vector一样有个reserve函数来预调配数据?65 set的底层实现实现为什么不必哈希表而应用红黑树?66 hash_map与map的区别?什么时候用hash_map,什么时候用map?67 迭代器生效的问题68 STL线程不平安的状况*这68道题的具体答案曾经整顿成PDF文档了,轻易截几张图看看吧: ...

October 23, 2020 · 1 min · jiezi

关于c++:cpp-包管理-vcpkg-安装记录

记录本人装置 cpp 包治理 vcpkg 的过程 [toc] 0. 开发环境1. 下载 vcpkg2. 编译装置3. 应用 vcpkg 的坑4. 结语 0. 开发环境操作系统 Windows10编译环境 visual studio 2017(尽管笔者应用 vs 开发,然而我的项目构建采纳 vs 内建的 cmake)1.下载 vcpkgvcpkg 我的项目地址:https://github.com/Microsoft/... 因为国内环境,不举荐间接下载(整个我的项目大概 80 MB),我举荐上面两种下载方式: 应用 Gitee 下载,Gitee 上有一个 vcpkg 减速下载的我的项目应用 https://gitclone.com/github.c... 下载,下载原理参见 Github下载速度慢 晋升github下载速度最新解决方案 跟龟速说拜拜(继续更新 保障计划可行 倡议珍藏)2. 编译装置间接运行 bootstrap-vcpkg.bat (Windows) 将生成的 vcpkg.exe 增加到用户 PATH 中,Windows 零碎登记后从新登录,使 PATH 刷新 如果 vcpkg 在运行时解体,倡议以 Debug 模式从新编译装置 vcpkg(保障应用 vs 调试时有短缺的调试信息),这样能够在解体时应用 vs attach 到 vcpkg 过程进行 debug 。笔者第一次装置时 vcpkg.exe 间接 crash,我从新编译一遍(设置 msbuild 为 debug 模式)后,attach 到 vcpkg.exe 后,发现抛出的异样显示 copy pwsh.exe powershell.exe 失败,大概率是因为 powershell 7 装置到了 C:Program Files ,而这个文件夹下的复制操作都须要管理员权限,导致 copy 操作失败而抛出异样。 ...

October 19, 2020 · 2 min · jiezi

关于c++:CPrimer5笔记

第一章命名空间:用于解决不同库,类和变量同名的问题,表明该对象出自何处。实质上是定义了对象的范畴,例如:不同文件夹代能够有同名的文件,文件夹作为命名空间将它们辨别。 第二章:2.1对象的含意(不是oop的“对象”):被存储的每一个值都占用了一块内存,而这块内存被称为存储值示意的的对象。二进制单位:bit(0和1)可寻址的最小内存块:byte(8bit)计算机存储根本单元:word(4/8 byte; 32位 64位) 字面值常量(本人的了解):一种从字面模式就晓得(数据类型)的能够用来初始化特定变量的值。 2.3援用:个别指左值援用,因为放到左边意思变成了取地址符。

October 18, 2020 · 1 min · jiezi

关于c++:vscode教训1

刚刚学会用装wsl,并且用vscode终端进入wsl操作文件。这样vscode既能实现linux操作,又能实现其内置的debug性能。 !如果,把default terminal改为wsl的话,应用f5将会报错(目前不分明起因),所以如果须要debug性能则不要把默认终端设置为wsl终端。 另外,vscode每装置一个拓展,或者是批改默认设置,最好重启一下,保障无效不发生意外谬误。

October 18, 2020 · 1 min · jiezi

关于c++:xmake-v238-发布-新增-Intel-CFortran-编译器支持

xmake 是一个基于 Lua 的轻量级跨平台构建工具,应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门,可能让用户把更多的精力集中在理论的我的项目开发上。 在这个新版本中,咱们对 Intel 系列的 C++ 和 Fortran 编译器做了全平台反对,并且改良了上个版本新加的 Wasm 工具链反对,同时对 Qt SDK for Wasm 也进行了反对。 另外,咱们还将 luajit 降级到最新的 v2.1 版本,在跨平台方面,xmake 也做了很大的欠缺,减少了 mips64 架构的运行反对。 我的项目源码官网文档入门课程新个性介绍Intel C++ 编译器反对这个版本上,咱们对 Intel 系列的 C++ 编译器做了全平台反对,包含 windows上的 icl 以及 linux/macOS 下的 icc/icpc。 要想启用 Intel C++ 编译器,咱们只须要在装置了的 Intel 编译器的零碎上,通过 --toolchain=icc 参数切换到对应的工具链即可。 $ xmake f --toolchain=icc$ xmakeIntel Fortran 编译器反对之前的版本,xmake 仅仅反对 gfortran 编译器,而这个版本,咱们也反对了 Intel Fortran 编译器,也就是 ifort,咱们也只须要切换到对应的 ifort 工具链即可应用。 ...

October 18, 2020 · 3 min · jiezi

关于c++:C结构体指针

构造体:用于寄存一组类型不同数据的汇合(collection). struct Student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu[3]={ {10101,″Li Lin″, ′M′, 18,87.5, ″103 Beijing Road″}, {10102,″Zhang Fun″,′M′,19,99, ″130 Shanghai Road″}, {10104,″Wang Min″,′F′, 20,78.5, ″1010 Zhongshan Road″} };指针用于寄存指标变量所在内存地址的变量,当然也能够寄存指针自身所在内存地址,套娃. type x; type *var = &x; type **var_adr = &var;构造体指针应用 typedef struct Books { char title[50]; char author[50]; char subject[100]; string str; int book_id; }Books; int main(){ Books *book1 = new Books; //须要动态分配空间 book1->string = '须要头部引入string类'; book1->book_id = 1; }

October 13, 2020 · 1 min · jiezi

关于c++:C语言指针详解

1为什么应用指针如果咱们定义了 char a=’A’ ,当须要应用 ‘A’ 时,除了间接调用变量 a ,还能够定义 char *p=&a ,调用 a 的地址,即指向 a 的指针 p ,变量 a( char 类型)只占了一个字节,指针自身的大小由可寻址的字长来决定,指针 p 占用 4 个字节。 但如果要援用的是占用内存空间比拟大货色,用指针也还是 4 个字节即可。 应用指针型变量在很多时候占用更小的内存空间。变量为了示意数据,指针能够更好的传递数据,举个例子: 第一节课是 1 班语文, 2 班数学,第二节课颠倒过去, 1 班要上数学, 2 班要上语文,那么第一节课下课后须要怎么作调整呢?计划一:课间 1 班学生全都去 2 班, 2 班学生全都来 1 班,当然,走的时候要携带上书本、笔纸、零食……局面一片狼藉;计划二:两位老师课间调换教室。 显然,计划二更好一些,计划二相似应用指针传递地址,计划一将内存中的内容从新“复制”了一份,效率比拟低。 在数据传递时,如果数据块较大,能够应用指针传递地址而不是理论数据,即进步传输速度,又节俭大量内存。一个数据缓冲区 char buf[100] ,如果其中 buf[0,1] 为命令号, buf[2,3] 为数据类型, buf[4~7] 为该类型的数值,类型为 int ,应用如下语句进行赋值: *(short*)&buf[0]=DataId;*(short*)&buf[2]=DataType;*(int*)&buf[4]=DataValue;数据转换,利用指针的灵便的类型转换,能够用来做数据类型转换,比拟罕用于通信缓冲区的填充。指针的机制比较简单,其性能能够被集中从新实现成更抽象化的援用数据模式函数指针,形如: #define PMYFUN (void*)(int,int) ,能够用在大量分支解决的实例当中,如某通信依据不同的命令号执行不同类型的命令,则能够建设一个函数指针数组,进行散转。在数据结构中,链表、树、图等大量的利用都离不开指针。2 指针是什么?操作系统将硬件和软件联合起来,给程序员提供的一种对内存应用的形象,这种形象机制使得程序应用的是虚拟存储器,而不是间接操作和应用实在存在的物理存储器。所有的虚拟地址造成的汇合就是虚拟地址空间。 内存是一个很大的线性的字节数组,每个字节固定由 8 个二进制位组成,每个字节都有惟一的编号,如下图,这是一个 4G 的内存,他一共有 4x1024x1024x1024 = 4294967296 个字节,那么它的地址范畴就是 0 ~ 4294967296 ,十六进制示意就是 0x00000000~0xffffffff ,当程序应用的数据载入内存时,都有本人惟一的一个编号,这个编号就是这个数据的地址。指针就是这样造成的。 ...

October 13, 2020 · 4 min · jiezi

关于c++:代码防御性编程的十条技巧

1 什么是防御性编程?顾名思义,防御性编程是一种粗疏、审慎的编程办法。为了开发牢靠的软件,咱们要设计零碎中的每个组件,以使其尽可能的”爱护”本人。咱们通过明确地在代码中对构想进行查看,这是一种致力,避免咱们的代码以将会展示错误行为的形式被调用。 防御性编程使咱们能够尽早的发现较小的问题,而不是等到它们倒退成大的劫难的时候才发现。其开发软件的过程是: 上面总结了一些防御性编程的拥护和支持者的意见: 反对者: 它升高了代码的效;即便是一个很小的额定代码也须要一些额定的执行工夫。它对于一个函数来说兴许不要紧,然而对于一个由10万个函数组成的零碎,问题就变得重大了。每种防御性的做法都须要一些额定的工作;支持者: 防御性编程能够节俭大量的调试工夫,使你能够去做更有意义的事件。编写能够失常运行、只是速度有些慢的代码,要远远好过大多数工夫都失常运行、然而有时候会解体的代码。防御性编程防止了大量的安全性问题。防御性编程技巧应用好的编码格调和正当的设计采纳良好的编码格调,来防备大多数编码谬误。如: const关键字:关键字const能够给读你代码的人传播十分有用的信息。例如,在函数的形参前增加const关键字意味着这个参数在函数体内不会被批改,属于输出参数。 同时,正当地应用关键字const能够使编译器很天然的爱护那些不心愿被批改的参数,避免其被无心的代码批改,缩小bug的呈现。 volatile关键字:在一些并行设施的硬件寄存器(如状态寄存器),中断服务子程序中会拜访到的全局变量以及多线程利用中被几个工作共享的变量前应用volatile关键字来避免编译优化。 static关键字:函数体内static变量的作用范畴为该函数体,不同于auto变量,该变量的内存只被调配一次,因而其值在下次调用时仍维持上次的值。在模块内的static全局变量能够被模块内的所有函数拜访,但不能被模块外其它函数拜访。在模块内的static函数只可能被这一模块内的其它函数调用,这个函数的应用范畴被限度在申明它的模块内。位操作运算中,尽可能应用<<、 >>、 &、|等运算符,尽可能少应用/、%、*运算符。变量和函数的命名要有意义,并且尽可能做到一个函数只做一件事件。多采纳面向对象的思维来编写代码。在投入到编码工作之前,先思考大体的设计方案,这也十分要害。不要仓促的编写代码欲速则不达,每敲一个字,都要想分明你要输出的是什么。在写每一行时都三思而后行。可能会呈现什么样的谬误?你是否曾经思考了所有可能呈现的逻辑分支?加快速度,井井有条的编程尽管看上去很平庸,但这确实是缩小缺点的好方法。 如C语言编程中,谋求速度的程序员常常会呈现的一个问题就是将”==”谬误的输出为”=”,而有些编译器并不会正告,这就会造成问题。 不要置信任何人这里是指用狐疑的眼光来扫视所有的输出和所有的后果,直到你能证实这段代码是正确的时候为止。 编码的指标要清晰,而不是简洁简略是一种美,不要让你的代码过于简单。即编写的代码肯定要逻辑清晰,可读性强。 编译时关上所有正告开关在你的代码中产生任何正告信息,都应立即修改代码。要晓得正告的呈现总是有起因的。即便你认为某个正告无关紧要,也不要束之高阁。 应用平安的数据结构咱们最常见的一些安全隐患大略是由缓冲溢出引起的。缓冲溢出是因为不正确的应用固定大小的数据结构而造成的。例如,如下这个代码: char * unsafe_copy(const char * source){ char *buffer = new char[10]; strcpy(buffer,source); return buffer;}如果source中的数据长度超过10个字符,它就会造成其它问题。咱们能够改成如下模式: char * safe_copy(const char * source){ char *buffer = new char[10]; strncpy(buffer,source,10); //用strncpy代替strcpy能够爱护这个代码段 return buffer;}查看所有的返回值如果一个函数返回一个值,他这样做必定是有理由的。查看这个返回值,如果返回值是一个错误代码,你就必须分别这个代码并解决所有的谬误。不要让谬误悄无声息的侵入你的程序;大多数难以觉察的谬误都是因为程序员没有查看返回值而呈现的。 审慎的解决内存对于在执行期间所获取的任何资源,必须彻底开释。 在申明地位初始化所有变量如果你意外的应用了一个没有初始化的变量,那么你的程序在每次运行的时候都将失去不同的后果,这取决于过后内存中的垃圾信息是什么。这样会造成很多随机的行为,给查找带来很多的麻烦。因而,须要在申明每个变量的时候就对它进行初始化。 同时,平时编码时还要留神一些细则提供默认的行为:Switch语句中将default case的执行明示进去。同样地,如果你要编写一些不带else子句的if语句,停下来想一想,你是否该解决这个逻辑上的默认状况查看数值的上上限:确保每次运算数值变量都不会溢出,即数据类型的应用要审慎留神强制转换是否正当申明变量,能够使变量的申明地位与应用它的地位尽量靠近,从而避免它烦扰代码的其余局部加正当的异样解决、日志文件正确设置常量优良的程序应该做到:关怀代码是否强壮确保每个构想都显示地体现在防御性代码中心愿代码对无用信息的输出有正确的行为在编程的时候认真思考本人所编写的代码编写能够爱护本人不受其他人的愚昧挫伤的代码。

October 13, 2020 · 1 min · jiezi

关于c++:浮点数的秘密

1 前言咱们在学习 C 语言时,通常认为浮点数和小数是等价的,并没有严格辨别它们的概念,这也并没有影响到咱们的学习,起因就是浮点数和小数是绑定在一起的,只有小数才应用浮点格局来存储。 其实,整数和小数能够都应用定点格局来存储,也能够都应用浮点格局来存储,但理论状况却是,C 语言应用定点格局存储整数,应用浮点格局存储小数,这是在 “数值范畴” 和 “数值精度” 两项重要指标之间谋求均衡的后果。 2 什么是浮点数?浮点型简略讲就是实数的意思。浮点数在计算机中用以近似示意任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是 2)的整数次幂失去,这种示意办法相似于基数为 10 的迷信记数法。 3 浮点数在内存中的存储首先明确一点,无论是整型、浮点型还是字符等等数据类型在计算机底层都是以二进制的形式存储的。 浮点数在内存中的存储和整数不同,因为整数都能够转换为一一对应的二进制数据。而浮点数的存储是由符号位 (sign) + 指数位 (exponent) + 小数位 (fraction) 组成。 int 和 float 同样占据四个字节的内存,然而 float 所能示意的最大值比 int 大得多,其根本原因是浮点数在内存中是以指数的形式存储。 浮点数转换到内存中存储的步骤分为如下三步: 将浮点数转换成二进制用迷信计数法示意二进制浮点数计算指数偏移后的值对于第3点:计算指数时须要加上偏移量(前面有介绍为什么应用偏移量),而偏移量的值与浮点数的类型无关( float 偏移量值为 127 ,double 偏移量值为 1023)。比如对于指数 6,float 与 double 类型偏移后的值别离为: float : 127 + 6 = 133double:1023 + 6 = 10294 实例浮点数19.625用float是如何存储的: 将浮点数转换成二进制:10011.101(将 19.625 整数局部采纳除 2 取余,小数局部采纳乘 2 取整法);用迷信计数法示意二进制浮点数:1.0011101*2^4;计算指数偏移后的值:127 + 4 = 131  (10000011);拼接综上所述,float 类型的 19.625 在内存中的值为:0 - 10000011 - 001 1101 0000 0000 0000 0000。5 float与double范畴和精度范畴float和double的范畴是由指数的位数来决定的。(因为示意的时候都是1.x * 2^Y的模式,所以疏忽了1.x的成果,间接取指数示意浮点数的范畴) ...

October 12, 2020 · 2 min · jiezi

关于c++:听说有人不了解柔性数组

1 引言定长数组包在平时的开发中,缓冲区数据收发时,如果采纳缓冲区定长包,假设大小是 1k,MAX_LENGTH为 1024。构造体如下: //  定长缓冲区struct max_buffer{    int   len;    char  data[MAX_LENGTH];};数据结构的大小 >= sizeof(int) + sizeof(char) * MAX_LENGTH为了避免数据溢出的状况,data 的长度个别会设置得足够大,但也正是因为这样,才会导致数组的冗余。 如果发送 512 字节的数据,  就会节约 512 个字节的空间, 平时通信时,大多数是心跳包,大小远远小于 1024,除了节约空间还耗费很多流量。 内存申请: if ((m_buffer = (struct max_buffer *)malloc(sizeof(struct max_buffer))) != NULL){    m_buffer->len = CUR_LENGTH;    memcpy(m_buffer->data, "max_buffer test", CUR_LENGTH);    printf("%d, %sn", m_buffer->len, m_buffer->data);}内存开释: free(m_buffer);m_buffer = NULL;指针数据包为了防止空间上的节约,咱们能够将下面的长度为 MAX_LENGTH 的定长数组换为指针, 每次应用时动静的开拓 CUR_LENGTH 大小的空间。数据包构造体定义: struct point_buffer{    int   len;    char  *data;};数据结构大小 >= sizeof(int) + sizeof(char *)但在内存调配时,须要两步进行: 需为构造体调配一块内存空间;为构造体中的成员变量分配内存空间;内存申请: if ((p_buffer = (struct point_buffer *)malloc(sizeof(struct point_buffer))) != NULL){    p_buffer->len = CUR_LENGTH;    if ((p_buffer->data = (char *)malloc(sizeof(char) * CUR_LENGTH)) != NULL)    {        memcpy(p_buffer->data, "point_buffer test", CUR_LENGTH);        printf("%d, %sn", p_buffer->len, p_buffer->data);    }}内存开释: free(p_buffer->data);free(p_buffer);p_buffer = NULL;尽管这样可能节约内存,然而两次调配的内存是不间断的, 须要别离对其进行治理,导致的问题就是须要对构造体和数据别离申请和开释内存,这样对于程序员来说无疑是一个劫难,因为这样很容易导致忘记开释内存造成内存泄露。 有没有更好的办法呢?那就是明天的主题柔性数组。 2 柔性数组什么是柔性数组?柔性数组成员(flexible array member)也叫伸缩性数组成员,这种代码构造产生于对动静构造体的需要。在日常的编程中,有时候须要在构造体中寄存一个长度动静的字符串,鉴于这种代码构造所产生的重要作用,C99 甚至把它支出了规范中: As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.柔性数组是 C99 规范引入的个性,所以当你的编译器提醒不反对的语法时,请查看你是否开启了 C99 选项或更高的版本反对。 ...

October 12, 2020 · 1 min · jiezi

关于c++:C语言高效编程与代码优化

英文原文:https://www.codeproject.com/A...翻译作者:码农网 – gunner 在本篇文章中,我收集了很多教训和办法。利用这些教训和办法,能够帮忙咱们从执行速度和内存应用等方面来优化C语言代码。 简介在最近的一个我的项目中,咱们须要开发一个运行在挪动设施上但不保障图像高质量的轻量级JPEG库。期间,我总结了一些让程序运行更快的办法。在本篇文章中,我收集了一些教训和办法。利用这些教训和办法,能够帮忙咱们从执行速度和内存应用等方面来优化C语言代码。 只管在C代码优化方面有很多的指南,然而对于编译和你应用的编程机器方面的优化常识却很少。 通常,为了让你的程序运行的更快,程序的代码量可能须要减少。代码量的减少又可能会对程序的复杂度和可读性带来不利的影响。这对于在手机、PDA等对于内存应用有很多限度的小型设施上编写程序时是不被容许的。因而,在代码优化时,咱们的座右铭应该是确保内存应用和执行速度两方面都失去优化。 申明实际上,在我的我的项目中,我应用了很多优化ARM编程的办法(该我的项目是基于ARM平台的),也应用了很多互联网下面的办法。但并不是所有文章提到的办法都能起到很好的作用。所以,我对有用的和高效的办法进行了总结收集。同时,我还批改了其中的一些办法,使他们实用于所有的编程环境,而不是局限于ARM环境。 哪里须要应用这些办法?没有这一点,所有的探讨都无从谈起。程序优化最重要的就是找出待优化的中央,也就是找出程序的哪些局部或者哪些模块运行迟缓亦或耗费大量的内存。只有程序的各局部通过了优化,程序能力执行的更快。 程序中运行最多的局部,特地是那些被程序外部循环反复调用的办法最该被优化。 对于一个有教训的码农,发现程序中最须要被优化的局部往往很简略。此外,还有很多工具能够帮忙咱们找出须要优化的局部。我应用过Visual C++内置的性能工具profiler来找出程序中耗费最多内存的中央。另一个我应用过的工具是英特尔的Vtune,它也能很好的检测出程序中运行最慢的局部。依据我的教训,外部或嵌套循环,调用第三方库的办法通常是导致程序运行迟缓的最次要的起因。 整形数如果咱们确定整数非负,就应该应用unsigned int而不是int。有些处理器解决无符号unsigned 整形数的效率远远高于有符号signed整形数(这是一种很好的做法,也有利于代码具体类型的自解释)。 因而,在一个严密循环中,申明一个int整形变量的最好办法是: register unsigned int variable_name;记住,整形in的运算速度高浮点型float,并且能够被处理器间接实现运算,而不须要借助于FPU(浮点运算单元)或者浮点型运算库。只管这不保障编译器肯定会应用到寄存器存储变量,也不能保障处理器解决能更高效解决unsigned整型,但这对于所有的编译器是通用的。 例如在一个计算包中,如果须要后果准确到小数点后两位,咱们能够将其乘以100,而后尽可能晚的把它转换为浮点型数字。 除法和取余数在规范处理器中,对于分子和分母,一个32位的除法须要应用20至140次循环操作。除法函数耗费的工夫包含一个常量工夫加上每一位除法耗费的工夫。 Time (numerator / denominator) = C0 + C1* log2 (numerator / denominator) = C0 + C1 * (log2 (numerator) - log2 (denominator))对于ARM处理器,这个版本须要20+4.3N次循环。这是一个耗费很大的操作,应该尽可能的防止执行。有时,能够通过乘法表达式来代替除法。例如,如果咱们晓得b是负数并且bc是个整数,那么(a/b)>c能够改写为a>(cb)。如果确定操作数是无符号unsigned的,应用无符号unsigned除法更好一些,因为它比有符号signed除法效率高。 合并除法和取余数在一些场景中,同时须要除法(x/y)和取余数(x%y)操作。这种状况下,编译器能够通过调用一次除法操作返回除法的后果和余数。如果既须要除法的后果又须要余数,咱们能够将它们写在一起,如下所示: int func_div_and_mod (int a, int b) { return (a / b) + (a % b);}通过2的幂次进行除法和取余数 如果除法中的除数是2的幂次,咱们能够更好的优化除法。编译器应用移位操作来执行除法。因而,咱们须要尽可能的设置除数为2的幂次(例如64而不是66)。并且仍然记住,无符号unsigned整数除法执行效率高于有符号signed整形除法。 typedef unsigned int uint;uint div32u (uint a) { return a / 32;}int div32s (int a){ return a / 32;}下面两种除法都防止间接调用除法函数,并且无符号unsigned的除法应用更少的计算机指令。因为须要移位到0和正数,有符号signed的除法须要更多的工夫执行。 ...

October 12, 2020 · 5 min · jiezi

关于c++:面试中常见的-C-语言与-C-区别的问题

C和C++的区别C语言是一种结构化语言,其偏重于数据结构和算法,属于过程性语言尽管在语法上C++齐全兼容C语言,然而两者还是有很多不同之处。上面将具体解说C和C++不同之处的常见考题关键字static在C和C++区别C和C++中都有关键字static关键字,那么static关键字在C和C++中的应用有什么区别?请简述之。 剖析问题:在C中,用static润饰的变量或函数,次要用来阐明这个变量或函数只能在本文件代码块中拜访,而文件内部的代码无权拜访。并且static润饰的变量寄存在段存储区。次要有以下两种用处。 定义部分动态变量部分动态变量存储在动态存储区,在程序运行期间都不会开释,只在申明时进行初始化,而且只能初始化一次,如果没有初始化,其主动初始化为0或空字符。具备局部变量的“记忆性”和生存周期“全局性”特点。局部变量的“记忆性”是指在两次函数调用时,第二次调用开始时,变量可能放弃上一次调用完结数的值。如下例:include <stdio.h>//20200505 公众号:C语言与CPP编程 void staticShow() { static int a=10; printf("a=%dn",a); a += 10; } int main() { for(int i=0;i<4;i++) { staticShow(); } return 0; } 运行后果 利用生存周期的“全局性”,能够改善函数返回指针的问题,局部变量的问题在于当函数退出时其生存周期完结。而利用static润饰的局部变量却能够缩短其生存期。如下所示: include <stdio.h>include <string.h>//20200505 公众号:C语言与CPP编程 char *p = NULL; char helloToStr(char b) { static char a[50]; a[0]='H'; a[1]='E'; a[2]='L'; a[3]='L'; a[4]='O'; strcpy(a+5,b); p=a; return a; }; int main(void) { printf("%sn",helloToStr("yang")); strcpy(p+5,"song"); printf("%sn",p); strcpy(p+5,"zhang"); printf("%sn",p); strcpy(p+5,"wang"); printf("%sn",p); return 0; ...

October 12, 2020 · 2 min · jiezi

关于c++:深拷贝与浅拷贝到底是什么

深复制也叫深拷贝; 浅拷贝和深拷贝 拷贝就是复制,创立正本。假如有对象A,A有属性t1,t2。那么,我通过拷贝A,失去B,B应该也有属性t1,t2,且A、B两个对象的每个属性,都应该是雷同的。 对于根本类型的属性t1,拷贝是没有疑义的。简略将值复制一份,就达到了拷贝的成果。而对于援用类型的属性t2来说,拷贝就有了两层含意。 第一层是,我只是将t2援用的地址复制一份给B的t2,的确达到了属性雷同的成果,能够了解为实现了拷贝,然而事实上,两个对象中的属性t2对应的是同一个对象。在B对象上对t2所指向的对象进行操作,就会影响到A对象中的t2的值。 第二层是,我将A的t2所指向的对象,假如为o1,残缺复制一份,假如为o2,将新的o2的地址给B的t2。也达到了复制的成果,且对B的t2所指向的o2进行操作,不会影响到A的t2所指向的o1。 拷贝的两层含意,对应了浅拷贝和深拷贝的概念,做了第一层,就是浅拷贝,做到第二层,就是深拷贝。 基于以上内容,很容易能够想到,浅拷贝比深拷贝要更快,然而,从拷贝的意义上来看,浅拷贝相较于深拷贝,要欠缺一点。 实例如下: include <iostream>using namespace std; //20200430 公众号:C语言与CPP编程 class CopyDemo { public: CopyDemo(int pa,char *cstr) //构造函数,两个参数 { this->a = pa; this->str = new char[1024]; //指针数组,动静的用new在堆上调配存储空间 strcpy(this->str,cstr); //拷贝过去 } //没写,C++会主动帮忙写一个复制构造函数,浅拷贝只复制指针,如下正文局部 //CopyDemo(CopyDemo& obj) //{ // this->a = obj.a; // this->str = obj.str; //这里是浅复制会出问题,要深复制 //} CopyDemo(CopyDemo& obj) //个别数据成员有指针要本人写复制构造函数,如下 { this->a = obj.a; // this->str = obj.str; //这里是浅复制会出问题,要深复制 this->str = new char[1024];//应该这样写 ...

October 12, 2020 · 1 min · jiezi

关于c++:如果编程语言是一门武功绝学

学习编程与文治绝学武侠小说中,各路侠客绿林好汉都是从基本功开始一招一式学起,把握了足够多的招式后,加之勤学苦练,质变引起量变,会有一天关上任督二脉顿悟出这些招式背地的哲学逻辑,成为一代宗师。在编程的学习过程中,咱们何尝不是从一招一式的函数、语法、个性等学起,把握了一门编程语言后,再学习另一门语言就会快很多,如同领有内功后,习得其余文治也会轻松很多。 如果编程语言是一门文治绝学,各语言别离是哪门文治绝学呢? 汇编语言汇编语言 - 易筋经汇编语言是计算机提供给用户的最快最无效的语言,也是可能利用计算机的所有硬件个性并可能间接管制硬件的惟一语言。采纳它编写的程序具备存储空间占用少、执行速度快的特点,这些是高级语言所无奈取代的。通常用在最底层的程序优化,硬件操作或嵌入式编程的场合,曾经很少有人间接编写汇编。 《天龙八部》中扫地僧练的就是少林派的独家秘法易筋经。扫地僧除了扫地之外,做的惟一一件事,就是参悟易筋经,几十年的修为,练就一门绝世武功,高深莫测,无坚不摧,高效,无招胜有招。 C 语言C 语言 - 九阳神功C 语言是一门面向过程的计算机编程语言,与 C++、Java 等面向对象编程语言有所不同。C 语言的设计指标是提供一种能以繁难的形式编译、解决低级存储器、仅产生大量的机器码以及不须要任何运行环境反对便能运行的编程语言。C 语言主要用途除了实现编程语言底层性能,还利用在实现操作系统,还在通信畛域也有很大的用武之地。尽管绝对用来开发利用层面略微显得蠢笨一点,然而在考究效率的底层施展空间十分微小。 C 语言高效、灵便、功能丰富、表达力强、作为一门根底的底层语言与九阳神功偏内功是统一的,九阳真经着重内力,不重招法,外面论述的其实也次要是“刚柔并济”的情理。一代武当宗师张三丰,就是以九阳内功为根底,才创制了武当一脉功夫。所以学好 C 语言,有弱小的内功后,再学习其余语言就会绝对轻松。 C++C++  - 九阴真经C++ 是 C 语言的继承,它既能够进行 C 语言的过程化程序设计,又能够进行以抽象数据类型为特点的基于对象的程序设计,还能够进行以继承和多态为特点的面向对象的程序设计。与 C 语言相比 C++ 减少了以下方面: 类型查看更为严格减少了面向对象的机制减少了泛型编程的机制(Template)。减少了异样解决。减少了运算符重载。减少了规范模板库(STL)。如果 C 语言是偏内功的九阳神功,那么 C++ 无异于《九阴真经》,两者都是很根底的,并且两者间有近缘,这两门把握精通之后天下武学皆能容易把握。。 《九阴真经》并重招式,威力弱小、博大精深,蕴含有数神奇招术(内功、轻功、拳、掌、腿、刀法、剑法、杖法、鞭法、指爪、点穴密技、疗伤法门、闭气神功、移魂大法等等),诡秘莫测,义理艰深难学,C++ 同样蕴含很多内容,还在不停的延申,简单、弱小、百科全书式的语言、在大规模我的项目背后简直无其余语言可及。 C++ 跟《九阴真经》一样,有很多误区容易陷入,比较突出的问题就是内存透露,如果使用不当,很容易落得跟周芷若、欧阳锋、梅超风等一样走火入魔。 javajava - 小无相功Java 是一门面向对象编程语言,不仅排汇了 C++ 语言的各种长处,还摒弃了 C++ 难以了解的多继承、指针等概念,因而 Java 语言具备功能强大和简略易用两个特色。Java 语言作为动态面向对象编程语言的代表,极好地实现了面向对象实践,容许程序员以优雅的思维形式进行简单的编程。 Java 具备简略性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java 能够编写桌面应用程序、Web 应用程序、分布式系统和嵌入式零碎应用程序等。 小无相功是金庸武侠小说《天龙八部》中「逍遥派」的一门内功,威力弱小。只有身具此功,再晓得其余文治的招式,倚仗其威力无比,能够模拟他人的绝学甚至胜于原版,没有学过此功的人很难分辨。这一特点与 Java 的分布式、解释性、可移植性、多线程、动静执行相似。 Java 体系宏大又提供很多网络技术的反对,正如小无相功为根基运行少林七十二绝技,而jvm体系又如同逍遥派体系。门下弟子泛滥又超群绝伦,名声煊赫,博采众长,独步天下。 ...

October 12, 2020 · 2 min · jiezi

关于c++:Linux配置C11编译环境

配置yum源此处咱们应用163的yum源,配置如下 首先备份/etc/yum.repos.d/CentOS-Base.repo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup下载对应版本repo文件, 放入/etc/yum.repos.d/(操作前请做好相应备份),以下为下载链接 https://mirrors.163.com/.help/CentOS6-Base-163.repo 运行以下命令生成yum缓存 yum clean allyum makecache<!--more--> 应用yum配置c++编译环境yum配置好之后,配置c++编译环境命令如下 yum -y install gcc gcc-g++装置实现之后c++环境即可配置好。 写一个hello worl代码如下 #include<iostream>using namespace std;int main(){ cout<<"Hello World!"<<endl; return 0;}以上代码保留文件名为aa.cpp,用c++编译并执行的操作如下 g++ -o hello aa.cpp./aa.cpp源码编译装置c++11编译环境因为yum自带的gcc版本过低,并且c++11须要gcc4.8以上版本反对,因而须要下载gcc4.8以上版本以反对c++11 查看本地gcc版本 gcc -v本次版本为gcc version 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC) 获取gcc4.8.2版本的source code 源码默认放在src目录下 cd /usr/local/srcwget http://gcc.skazkaforyou.com/releases/gcc-4.8.2/gcc-4.8.2.tar.gz文件有100M,国外网站下载速度很慢,请急躁期待(可用国外vps下载直达) 下载实现后,放在/usr/local/src下 解压缩 tar -zxvf gcc-4.8.2.tar.gz编译源码并装置 进入gcc目录 cd gcc-4.8.2下载配置装置gcc4.8.2的依赖库 ./contrib/download_prerequisites建设编译输入目录 在以后门路下执行即可 mkdir gcc-build-4.8.2开始configure ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib--enable-languages示意你要让你的gcc反对那些语言--disable-multilib不生成编译为其余平台可执行代码的穿插编译器--disable-checking生成的编译器在编译过程中不做额定查看编译 在编译输入目录gcc-build-4.8.2间接make即可 make源码make过程耗时较长,个别须要半个小时以上。 ...

October 10, 2020 · 1 min · jiezi

关于c++:2020年10月技术笔记

41W(20201004-20201010)20201010ulimit -c的设置 普通用户没有权限的时候,怎么设置。如同无解“ulimit -c unlimited-bash: ulimit: core file size: cannot modify limit: Operation not permitted” + [ulimit调优|设置普通用户的ulimit值](https://www.cnblogs.com/kabi/p/5191928.html)SIGENV的信号,问题 对于SIGSEGV谬误及解决办法

October 9, 2020 · 1 min · jiezi

关于c++:xmake-官方入门课程上线-Xmake-带你轻松构建-CC-项目

实验楼课程Xmake 带你轻松构建 C/C++ 我的项目 是咱们在试验楼上推出的一门 xmake 入门和进阶课程(免费),以边学边做试验的形式疾速学习 xmake 的应用。 通过此处优惠码购买可享 9 折优惠:NYFbmf3X xmake 介绍Xmake 是一个基于 Lua 的轻量级跨平台 C/C++ 构建工具,应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt 而言,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门 C/C++ 我的项目的编译开发,提供一站式跨平台编译、运行、调试、打包、装置等操作,可能让大家把更多的精力集中在理论的我的项目开发上。 尽管,简略易用是 xmake 的一大特色,但 xmake 的性能也是十分弱小的,既可能像 make/ninja 那样间接编译我的项目,也能够像 cmake/meson 那样生成工程文件,还有内置的包管理系统来帮忙大家解决 C/C++ 依赖库的集成应用问题。 课程介绍本课程以循序渐进的形式,带你入门和进阶 xmake,从最根底的编译配置,到简单我的项目的定制化组织和保护,在课程最初几节,咱们还通过实战的形式,一步步带你体验第三方 C/C++ 我的项目的移植编译,以及 vscode/xmake 集成环境的可视化编译操作流程。最初一节试验中,咱们还会解说如何应用 xmake 和 vscode 去编译开发基于 Qt 的应用程序。 你将学到 C/C++ 程序的编译运行和调试xmake 根底命令应用C/C++ 依赖库集成和应用大型工程构造的保护xmake 简单脚本和规定的编写如何实现跨平台编译xmake 插件开发VS Code/xmake 集成环境的应用xmake 的根底语法C/C++ 我的项目根底编译配置多个目标程序的依赖编译预编译头文件的设置cmake/makefile 工程文件的生成xmake 脚本运行插件的应用C/C++ 代码的移植编译Qt 我的项目程序的编译开发课程链接链接地址:https://www.lanqiao.cn/courses/2764 ...

October 9, 2020 · 1 min · jiezi

关于c++:make从入门到入门

makefile文件是用来帮忙编译和治理C++我的项目代码的,须要配合make命令应用。makefile里也能够执行shell操作,具备一部分.sh脚本的性能。 makefile格局makefile内容的编写依照如下规定 指标1:依赖1 命令1指标2:依赖2 命令2指标3:依赖3 命令3.........................指标N:依赖N 命令N命令能够是任意的shell语句。少数状况下,命令都是起到了从依赖生成指标的性能。例如从.cpp文件生成.o文件,那么命令肯定包含g++和一些编译参数的残缺的编译命令。 指标1 2 3能够是嵌套依赖的,如果依赖1里蕴含指标2 指标3,那就是一种嵌套的依赖。也能够是独立的,例如指标1 2 3就是三个独立的可执行文件,或者三个动静库,那么他们之间是能够齐全没有依赖关系的,写在一个makefile文件里只是便于对立治理。 命令前要以一个tab结尾 。如果应用空格代替tab,执行make命令时会报 [root@localhost makefiletest]# makemakefile:5: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.举个例子以上面简略的C++代码为例,阐明makefile的具体应用。 源代码文件test.cpp #include <string>#include <iostream>#include<iomanip>int main(int argc, char** argv){using namespace std;int i =1 ;int j = 2; j += 3;cout << j<<endl;}makefile文件,文件就是makefile CC=g++all = test.otest: $(all)$(CC) -o test $(all)test.o: ./test.cpp$(CC) -c test.cppclear: rm -f *.o test执行make命令 [root@localhost makefiletest]# makeg++ -c test.cppg++ -o test test.o[root@localhost makefiletest]# ls -lrttotal 24-rw-r--r--. 1 root root 196 Aug 6 11:00 test.cpp-rw-r--r--. 1 root root 120 Aug 6 11:04 makefile-rw-r--r--. 1 root root 2328 Aug 6 11:04 test.o-rwxr-xr-x. 1 root root 8840 Aug 6 11:04 test正确生成了test和test.o ...

October 6, 2020 · 1 min · jiezi

关于c++:VSCode-C开发环境配置文件WindowsMac

Windows(应用MSVC编译)c_cpp_properties.json{ "configurations": [ { "name": "Win32", "includePath": [ "${workspaceFolder}/**" ], "defines": [ "_DEBUG", "UNICODE", "_UNICODE" ], "windowsSdkVersion": "8.1", "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe", "cStandard": "c11", "cppStandard": "c++17", "intelliSenseMode": "msvc-x64" } ], "version": 4}launch.json{ "version": "0.2.0", "configurations": [ { "name": "cl.exe - 生成和调试流动文件", "type": "cppvsdbg", "request": "launch", "program": "${fileDirname}\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "preLaunchTask": "C/C++: cl.exe build active file" } ]}tasks.json{ "version": "2.0.0", "tasks": [ { "label": "msvc build", "type": "shell", "command": "cl.exe", "args": [ "/EHsc", "/Zi", "/Fe:", "main.exe", "main.cpp" ], "group": "build", "presentation": { "reveal": "always" }, "problemMatcher": "$msCompile" }, { "type": "shell", "label": "C/C++: cl.exe build active file", "command": "cl.exe", "args": [ "/Zi", "/EHsc", "/Fe:", "${fileDirname}\\${fileBasenameNoExtension}.exe", "${file}" ], "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": [ "$msCompile" ], "group": { "kind": "build", "isDefault": true } } ]}Windows中应用MSVC来编译源文件肯定要通过VS提供的Developer Command Prompt(开发人员命令提醒)工具来关上。打开方式是: ...

October 6, 2020 · 2 min · jiezi

关于c++:从零搭建wondertrader的开发环境

前言WonderTrader开源以来,尽管没有正式做过推广,然而逐步有了第一批吃螃蟹的用户。在此WonderTrader团队对这些用户深表感激,心愿WonderTrader可能取得大家更多的认可。在用户的反馈中,咱们逐步发现,除了间接应用wtpy进行回测和交易的用户,还有一批对源码有间接需要的用户。他们在应用过程中遇到的最大问题是如何编译源码。WonderTrader的官网文档中,对开发环境做了简略的介绍,然而并不深刻,所以这些用户在搭建开发环境的过程中遇到了不少问题。本文的次要目标就是帮忙用户解决WonderTrader的源码的编译问题。鉴于个别用户对于windows平台下搭建开发环境都比拟相熟,所以本文将重点介绍linux下的开发环境的搭建。 共享资源因为笔者长期在开发一线,平时在工作中会用到很多不便易用的工具,WonderTrader的开发中也有波及。为了不便大家下载应用,本文中波及到的一些好用的工具,笔者都对立放到百度云盘里共享进去,大家能够依据须要自行下载。文中会有多出波及到从共享资源中下载文件,前面就不再赘述,对立用共享资源代称。下载连贯:https://pan.baidu.com/s/1Bdxh... 提取码: d6bh Linux开发环境搭建操作系统:Ubuntu Server 18.04.3 LTSUbuntu 20当前的秘钥加密算法做了调整,SecureCRT 7以前的版本都无奈连贯,所以本文以Ubuntu 18.04.3 LTS版本作为根本环境。笔者将应用vmware装置一个全新环境,从零开始演示开发环境如何搭建。 1、应用vmware装置ubuntu server 18.04.3 LTS镜像镜像能够从共享资源中间接下载 2、虚拟机创立胜利当前,主动开启,进入装置界面,而后一路默认 3、到了源配置界面,肯定要把镜像改为国内镜像!这个很重要!不然装置特地慢!举荐应用阿里云的源http://mirrors.aliyun.com/ubuntu 4、到了SSH配置界面,肯定要抉择SSH server,不然会无奈应用putty或SecureCRT 5、到了组件抉择界面,不必装置多余的组件,间接done 6、进入最初流程这里会有平安降级,可能耗时较长(如果后面没有配置国内镜像,这里的工夫更是数倍),也能够跳过平安降级 7、重启之后,进入控制台如果应用SecureCRT连贯,在vmware中能够看一下虚拟机的ip地址,而后配置连贯地址和账号密码进行连贯 8、装置开发环境$ sudo apt-get install build-essential 应用gcc --version查看gcc的版本号 装置cmake 应用cmake --version查看cmake的版本号 装置7z解压工具 $ sudo apt-get install p7zip-full 9、从共享资源中下载mydes_linux.7z并上传到虚拟机能够应用应用SecureFX(共享资源中的SecureCRT自带SecureFX)上传到虚拟机,如下图: 10、将mydeps_linux.7z解压到/home下$ sudo 7z x mydeps_linux.7z /home11、拉取WonderTrader的源码$ sudo git clone https://github.com/wondertrader/wondertrader.git 12、进入src目录,执行编译脚本$ sudo ./build_release.sh编译实现当前,应用SecureFX就能够间接从src目录下的build/bin中下载须要的文件即可 Windows开发环境搭建1、装置vs2017社区版首先下载vs2017的装置器,下载地址如下:https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/ 或者间接从共享资源中间接下载该装置器 2、从共享资源中下载vc141deps_win.7z,并解压到E:/vc141depends目录 3、配置环境变量从共享资源中下载环境变量编辑器RapidEE到本地,解压当前运行。新建一个名为MyDepends141的环境变量,并将值设置为依赖库解压目录E:/vc141depends设置好了当前,保留环境变量,即可失效,如果没有失效,能够重启电脑。win10下要留神一下应用管理员身份运行RapidEE,不然保留可能会失败! 4、装置git下载git并装置:https://git-scm.com/download/win下载tortoisegit并装置:https://tortoisegit.org/download/ 5、下载代码抉择一个目录,而后右键点击该目录,抉择“Git克隆”菜单URL设置为:https://github.com/wondertrad... 6、编译代码进入到wondertrader的src目录下双击运行wondertrader.sln,关上当前在解决方案上右键点击,抉择“生成解决方案”就进入了编译过程 结束语置信通过本文,大家都可能对如何编译WonderTrader的源码有了一个更加全面的意识。WonderTrader旨在打造一个集投研治理、数据服务、策略回测、产品经营为一体的一站式的量化交易平台。笔者心愿通过WonderTrader可能帮忙各位市场参与者省去不必要的造轮子的精力,将更多的注意力放在策略研发和团队治理自身,进步管理效率,促成量化交易平台零碎的进一步成熟。最初再来一波广告WonderTrader的github地址:https://github.com/wondertrad...WonderTrader官网地址:https://wondertrader.github.iowtpy的github地址:https://github.com/wondertrad...

October 4, 2020 · 1 min · jiezi

关于c++:C-参考手册C语言参考手册

C++ 参考手册C++98, C++03, C++11, C++14, C++17, C++20 编译器反对 (11, 14, 17, 20)自立实现 语言 基本概念关键词预处理器表达式申明初始化函数语句类重载模板异样 头文件 具名要求 性能个性测试宏 (C++20) 语言反对库 类型反对  −   个性 (C++11)程序工具关系运算符 (C++20)numeric_limits  −  type_infoinitializer_list (C++11) 概念库 (C++20) 诊断库 通用工具库 智能指针与分配器日期和工夫函数对象  −  hash (C++11)字符串转换 (C++17)工具函数pair  −   tuple (C++11)optional (C++17)  −  any (C++17)variant (C++17)  −  format (C++20) 字符串库 basic_stringbasic_string_view (C++17)空终止字符串:   字节  −   多字节  −   宽 容器库 array (C++11)  −  vectormap  −  unordered_map (C++11)priority_queue  −  span (C++20)其余容器:  程序  −  关联  无序关联  −  适配器 迭代器库 范畴库 (C++20) 算法库 数值库 罕用数学函数数学非凡函数 (C++17)数值算法伪随机数生成浮点环境 (C++11)complex  −  valarray 输出/输入库 基于流的 I/O同步输入 (C++20)I/O 操纵符 文件系统库 (C++17) 本地化库 正则表达式库 (C++11) basic_regex  −  算法 ...

September 28, 2020 · 1 min · jiezi

关于c++:从四个问题透析Linux下C编译链接

摘要:编译&链接对C&C++程序员既相熟又生疏,相熟在于每份代码都要经验编译&链接过程,生疏在于大部分人并不会刻意关注编译&链接的原理。本文通过开发过程中碰到的四个典型问题来摸索64位linux下C++编译&链接的那些事。编译原理:将如下最简略的C++程序(main.cpp)编译成可执行目标程序,实际上能够分为四个步骤:预处理、编译、汇编、链接,能够通过 g++ main.cpp –v看到具体的过程,不过当初编译器曾经把预处理和编译过程合并。 预处理:g++ -E main.cpp -o main.ii,-E示意只进行预处理。预处理次要是解决各种宏开展;增加行号和文件标识符,为编译器产生调试信息提供便当;删除正文;保留编译器用到的编译器指令等。 编译:g++ -S main.ii –o main.s,-S示意只编译。编译是在预处理文件根底上通过一系列词法剖析、语法分析及优化后生成汇编代码。 汇编:g++ -c main.s –o main.o。汇编是将汇编代码转化为机器能够执行的指令。 链接:g++ main.o。链接生成可执行程序,之所以须要链接是因为咱们代码不可能像main.cpp这么简略,古代软件动则成千盈百万行,如果写在一个main.cpp既不利于分工合作,也无奈保护,因而通常是由一堆cpp文件组成,编译器别离编译每个cpp,这些cpp里会援用别的模块中的函数或全局变量,在编译单个cpp的时候是没法晓得它们的精确地址,因而在编译完结后,须要链接器将各种还没有精确地址的符号(函数、变量等)设置为正确的值,这样组装在一起就能够造成一个残缺的可执行程序。 问题一:头文件遮挡在编译过程中最诡异的问题莫过于头文件遮挡,如下代码中main.cpp蕴含头文件common.h,真正想用的头文件是图中最左边那个蕴含name 成员的文件(所在目录为./include),但在编译过程中两头的common.h(所在目录为./include1)领先被发现,导致编译器报错:Test构造没有name成员,对程序员来讲,本人明明定义了name成员,竟然说没有name这个成员,如果第一次碰到这种状况可能会狐疑人生。应答这种诡异的问题,咱们能够用-E参数看下编译器预处理后的输入,如下图。 预处理文件格式如下:# linenum filename flag,示意之后的内容是从文件名为filaname的文件中第linenum行开展的,flag的取值能够是1,2,3,4,能够是用空格离开的多值,1示意接下来要开展一个新文件;2示意一个文件开展结束;3示意接下来内容来自一个零碎头文件;4示意接下来的内容应该看做是extern C模式引入的。 从开展后的输入咱们能够分明地看到Test构造的确没有定义name这个成员,并且Test这个构造是在./include1中的common.h中定义的,到此水落石出,编译器压根就没用咱们定义的Test构造,而是被别的同名头文件截胡了。咱们能够通过调整-I或者在头文件中带上局部门路更具体制订头文件地位来解决。 指标文件: 编译链接最终会生成各种指标文件,Linux下指标文件格式为ELF(Executable Linkable Format),具体定义见/usr/include/elf.h头文件,常见的指标文件有:可重定位指标文件,也即.o结尾的指标文件,当然动态库也归为此类;可执行文件,比方默认编译出的a.out文件;共享指标文件.so;外围转储文件,也就是core dump后产出的文件。Linux文件格式能够通过file命令查看。 一个典型的ELF文件格式如下图所示,文件有两种视角:编译视角,以section头部表为外围组织程序;运行视角,程序头部表以segment为外围组织程序。这么做次要是为了节约存储,很多细碎的section在运行时因为对齐要求会导致很大的内存节约,运行时通常会将权限相似的section组织成segment一起加载。 通过命令objdump和readelf能够查看ELF文件的内容。 对可重定位指标文件常见的section有: 符号解析: 链接器会为对外部符号的援用批改为正确的被援用符号的地址,当无奈为援用的内部符号找到对应的定义时,链接器会报undefined reference to XXXX的谬误。另外一种状况是,找到了多个符号的定义,这种状况链接器有一套规定。在形容规定前须要理解强符号和弱符号的概念,简略讲函数和已初始化的全局变量是强符号,未初始化的全局变量是弱符号。 针对符号的多重定义链接器解决规定如下(作者在gcc 7.3.0上貌似规定2,3都按1解决): 不容许多个强符号定义,链接器会报告反复定义貌似的谬误如果一个强符号和多个弱符号同名,则抉择强符号如果符号在所有指标文件中都为弱符号,那么抉择占用空间最大的一个有了这些根底,咱们先来看一下动态链接过程: 链接器从左到右依照命令行呈现程序扫描指标文件和动态库链接器保护一个指标文件的汇合E,一个未解析符号汇合U,以及E中已定义的符号汇合D,初始状态E、U、D都为空对命令行上每个文件f,链接器会判断f是否是一个指标文件还是动态库,如果是指标文件,则f退出到E,f中未定义的符号退出到U中,已定义符号退出到D中,持续下一文件如果是动态库,链接器尝试到动态库指标文件中匹配U中未定义的符号,如果m中匹配U中的一个符号,那么m就和上步中文件f一样解决,对每个成员文件都顺次解决,直到U、D无变动,不蕴含在E中的成员文件简略抛弃所有输出文件解决完后,如果U中还有符号,则出错,否则链接失常,输入可执行文件问题二:动态库程序如下图所示,main.cpp依赖liba.a,liba.a又依赖libb.a,依据动态链接算法,如果用g++ main.cpp liba.a libb.a的程序能失常链接,因为解析liba.a时未定义符号FunB会退出到上述算法的U中,而后在libb.a中找到定义,如果用g++ main.cpp libb.a liba.a的程序编译,则无奈找到FunB的定义,因为依据动态链接算法,在解析libb.a的时候U为空,所以不须要做任何解析,简略摈弃libb.a,但在解析liba.a的时候又发现FunB没有定义,导致U最终不为空,链接谬误,因而在做动态链接时,须要特地留神库的程序安顿,援用别的库的动态库须要放在后面,碰到链接很多库的时候,可能须要做一些库的调整,从而使依赖关系更清晰。 动静链接: 之前大部分内容都是动态链接相干,但动态链接有很多有余:不利于更新,只有有一个库有变动,都须要从新编译;不利于共享,每个可执行程序都独自保留一份,对内存和磁盘是极大的节约。 要生成动态链接库须要用到参数“-shared -fPIC”示意要生成地位无关PIC(Position Independent Code)的共享指标文件。对动态链接,在生成可执行指标文件时整个链接过程就实现了,但要想实现动静链接的成果,就须要把程序依照模块拆分成绝对独立的局部,在程序运行时将他们链接成一个残缺的程序,同时为了实现代码在不同程序间共享要保障代码是和地位无关的(因为共享指标文件在每个程序中被加载的虚拟地址都不一样,要保障它不论被加载在哪都能工作),而为了实现地位无关又依赖一个前提:数据段和代码段的间隔总是放弃不变。 因为不论在内存中如何加载一个指标模块,数据段和代码段间的间隔是不变的,编译器在数据段后面引入了一个全局偏移表GOT(Global Offset Table),被援用的全局变量或者函数在GOT中都有一条记录,同时编译器为GOT中每个条目生成一个重定位记录,因为数据段是能够批改的,动静链接器在加载时会重定位GOT中的每个条目,这样就实现了PIC。 ...

September 27, 2020 · 1 min · jiezi

关于c++:asyncawait-如何工作-Rust学习笔记

2019年底Rust正式反对 async/await语法,实现了Rust协程的最初一块拼图,从而异步代码能够用一种相似于Go的简洁形式来书写。然而对于程序员来讲,还是很有必要了解async/await的实现原理。 async简略地说,async语法生成一个实现 Future 对象。如下async函数: async fn foo() -> { ...}async关键字,将函数的原型批改为返回一个Future trait object。而后将执行的后果包装在一个新的future中返回,大抵相当于: fn foo() -> impl Future<Output = ()> { async { ... }}更重要的是async 代码块会实现一个匿名的 Future trait object ,包裹一个 Generator。也就是一个实现了 Future 的 Generator。Generator实际上是一个状态机,配合.await当每次async 代码块中任何返回 Poll::Pending则即调用generator yeild,让出执行权,一旦复原执行,generator resume 继续执行残余流程。 以下是这个状态机Future的代码: pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>where T: Generator<ResumeTy, Yield = ()>,{ struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T); impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {} impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> { type Output = T::Return; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) { GeneratorState::Yielded(()) => Poll::Pending, // 当代码无奈继续执行,让出控制权,返回 Pending,期待唤醒 GeneratorState::Complete(x) => Poll::Ready(x), // 执行结束 } } } GenFuture(gen)}能够看到这个特地的Future是通过Generator来运行的。每一次gen.resume()会程序执行async block中代码直到遇到yield。async block中的.await语句在无奈立刻实现时会调用yield交出控制权期待下一次resume。而当所有代码执行完,也就是状态机进入Complete,async block返回Poll::Ready,代表Future执行结束。 ...

September 22, 2020 · 1 min · jiezi

关于c++:OpenCV的Mat类型以及基本函数使用

OpenCV的Mat类型以及根本函数应用Mat和IplImage的区别Mat和IplImage的次要区别在OpenCV中IplImage是示意一个图像的构造体,也是从OpenCV1.0到目前最为重要的一个构造;在之前的图像示意用IplImage,而且之前的OpenCV是用C语言编写的,提供的接口也是C语言接口。 Mat是起初OpenCV封装的一个C++类,用来示意一个图像,和IplImage示意基本一致,然而Mat还增加了一些图像函数。 IplImageIplImage数据结构的定义在opencvbuildincludeopencv2coretypes_c.h文件中。 typedef struct _IplImage{ int nSize; /* sizeof(IplImage) */ int ID; /* version (=0)*/ int nChannels; /* Most of OpenCV functions support 1,2,3 or 4 channels */ int alphaChannel; /* Ignored by OpenCV */ int depth; /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */ char colorModel[4]; /* Ignored by OpenCV */ char channelSeq[4]; /* ditto */ int dataOrder; /* 0 - interleaved color channels, 1 - separate color channels. cvCreateImage can only create interleaved images */ int origin; /* 0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style). */ int align; /* Alignment of image rows (4 or 8). OpenCV ignores it and uses widthStep instead. */ int width; /* Image width in pixels. */ int height; /* Image height in pixels. */ struct _IplROI *roi; /* Image ROI. If NULL, the whole image is selected. */ struct _IplImage *maskROI; /* Must be NULL. */ void *imageId; /* " " */ struct _IplTileInfo *tileInfo; /* " " */ int imageSize; /* Image data size in bytes (==image->height*image->widthStep in case of interleaved data)*/ char *imageData; /* Pointer to aligned image data. */ int widthStep; /* Size of aligned image row in bytes. */ int BorderMode[4]; /* Ignored by OpenCV. */ int BorderConst[4]; /* Ditto. */ char *imageDataOrigin; /* Pointer to very origin of image data (not necessarily aligned) - needed for correct deallocation */}IplImage;可见,IplImage是一个示意图像的构造体:C语言操作OpenCV的数据结构。位置等同于Mat,能够说是历史版本了。 ...

September 22, 2020 · 7 min · jiezi

关于c++:linux下C多线程并发之原子操作与无锁编程

一、何为原子操作原子操作:顾名思义就是不可分割的操作,该操作只存在未开始和已实现两种状态,不存在中间状态; 原子类型:原子库中定义的数据类型,对这些类型的所有操作都是原子的,包含通过原子类模板std::atomic< T >实例化的数据类型,也都是反对原子操作的。 二、如何应用原子类型2.1 原子库atomic反对的原子操作 原子库< atomic >中提供了一些根本原子类型,也能够通过原子类模板实例化一个原子对象,上面列出一些根本原子类型及相应的特化模板如下: 对原子类型的拜访,最次要的就是读和写,但原子库提供的对应原子操作是load()与store(val)。原子类型反对的原子操作如下: 2.2 原子操作中的内存拜访模型 原子操作保障了对数据的拜访只有未开始和已实现两种状态,不会拜访到中间状态,但咱们拜访数据个别是须要特定程序的,比方想读取写入后的最新数据,原子操作函数是反对管制读写程序的,即带有一个数据同步内存模型参数std::memory_order,用于对同一时间的读写操作进行排序。C++11定义的6种类型如下: memory_order_relaxed: 宽松操作,没有同步或程序制约,仅对此操作要求原子性;memory_order_release & memory_order_acquire: 两个线程A&B,A线程Release后,B线程Acquire能保障肯定读到的是最新被批改过的值;这种模型更弱小的中央在于它能保障产生在A-Release前的所有写操作,在B-Acquire后都能读到最新值;memory_order_release & memory_order_consume: 上一个模型的同步是针对所有对象的,这种模型只针对依赖于该操作波及的对象:比方这个操作产生在变量a上,而s = a + b; 那s依赖于a,但b不依赖于a; 当然这里也有循环依赖的问题,例如:t = s + 1,因为s依赖于a,那t其实也是依赖于a的;memory_order_seq_cst: 程序一致性模型,这是C++11原子操作的默认模型;大略行为为对每一个变量都进行Release-Acquire操作,当然这也是一个最慢的同步模型;内存拜访模型属于比拟底层的管制接口,如果对编译原理和CPU指令执行过程不理解的话,容易引入bug。内存模型不是本章重点,这里不再开展介绍,后续的代码都应用默认的程序一致性模型或比拟稳当的Release-Acquire模型。 须要C/C++ Linux服务器架构师学习材料加群563998835获取(材料包含C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),收费分享 2.3 应用原子类型代替互斥锁编程 为便于比拟,间接基于前篇文章:线程同步之互斥锁中的示例程序进行批改,用原子库取代互斥库的代码如下: //atomic1.cpp 应用原子库取代互斥库实现线程同步#include <chrono>#include <atomic>#include <thread>#include <iostream> std::chrono::milliseconds interval(100);std::atomic<bool> readyFlag(false); //原子布尔类型,取代互斥量std::atomic<int> job_shared(0); //两个线程都能批改'job_shared',将该变量特化为原子类型int job_exclusive = 0; //只有一个线程能批改'job_exclusive',不须要爱护//此线程只能批改 'job_shared'void job_1(){ std::this_thread::sleep_for(5 * interval); job_shared.fetch_add(1); std::cout << "job_1 shared (" << job_shared.load() << ")n"; readyFlag.store(true); //扭转布尔标记状态为真}// 此线程能批改'job_shared'和'job_exclusive'void job_2(){ while (true) { //有限循环,直到可拜访并批改'job_shared' if (readyFlag.load()) { //判断布尔标记状态是否为真,为真则批改‘job_shared’ job_shared.fetch_add(1); std::cout << "job_2 shared (" << job_shared.load() << ")n"; return; } else { //布尔标记为假,则批改'job_exclusive' ++job_exclusive; std::cout << "job_2 exclusive (" << job_exclusive << ")n"; std::this_thread::sleep_for(interval); } }}int main() { std::thread thread_1(job_1); std::thread thread_2(job_2); thread_1.join(); thread_2.join(); getchar(); return 0;}由示例程序能够看出,原子布尔类型能够实现互斥锁的局部性能,但在应用条件变量condition variable时,依然须要mutex爱护对condition variable的生产,即便condition variable是一个atomic object。 ...

September 21, 2020 · 2 min · jiezi

关于c++:WonderTrader发布v052版本

明天(2020年9月21日)WonderTrader公布了v0.5.2版本,wtpy的最新版本会跟着公布。 WonderTrader在v0.5.2中做了如下批改:批改CTPLoader为显式加载CTP模块,不便设置CTP模块的门路。将所有的通道对接模块(行情、交易)改成显示加载三方依赖库,并对立查看了版本的一致性。修改了股票Level2数据落地的一些细节问题,数据组件曾经齐全适配Level2数据的接入。修改了风控触发时,限度手数比例为小数时,没有进行四舍五入导致的问题。历史数据新增了对Mysql数据库的反对,波及到的模块包含数据读取模块WtDataReader、数据落地模块WtDataWriter、回测框架WtBtCore,Mysql库版本为6.11。如果配置了mysql数据库,开盘作业时将会主动将实时的数据写到数据库里,作为历史数据存起来。(tick以及level2数据因为占用空间大,依然按二进制文件的形式压缩存储)修改了数据组件UDP播送模块中,直达的播送音讯对象对WTSObject的解决的bug。wtpy在v0.5.2中做了如下批改:同步WonderTrader外围为v0.5.2监控服务monitor减少了一个日志模块WtLogger.py,外部应用logging模块来记录日志进一步欠缺了web-ui的局部性能和配色新增一个CTPLoader模块,次要用于调用底层CTPLoader执行程序,用于从CTP账号加载合约列表下一个阶段的打算持续欠缺文档公布更多的策略利用的公众号文章近程控制台集成更多功能(主动部署、在线回测)提供更多易用性方面的改良外围性能测试优化

September 21, 2020 · 1 min · jiezi

关于c++:技术解析丨C元编程之Parser-Combinator

摘要:借助C++的constexpr能力,能够轻而易举的结构Parser Combinator,对用户定义的字符串(User defined literal)开释了微小的后劲。引子前不久在CppCon上看到一个Talk:constexpr All the things,这个演讲技术令我十分震惊,在编译期解析json字符串,进而提出了编译期结构正则表达式(编译期构建FSM),现场掌声一片,而背地依附的是C++弱小的constexpr个性,从而大大提高了编译期计算威力。 早在C++11的时候就有constexpr个性,那时候束缚比拟多,只能有一条return语句,能做的事件只有简略的递归实现一些数学、hash函数;而到了C++14的时候这个束缚放开了,容许像一般函数那样,进而社区产生了一系列constexpr库;而在C++17,更加泛化了constexpr,容许if constexpr来代替元编程的SFINAE手法,STL库的一些算法反对constexpr,甚至连lambda都默认是constexpr的了;到C++20,更加难以想象,竟然反对了constexpr new,STL的vector都是constexpr的了,若用constexpr allocator和constexpr destructor,那么就能对立所有constexpr容器了。 借助C++的constexpr能力,能够轻而易举的结构Parser Combinator,实现一个Parser也没那么繁冗了,对用户定义的字符串(User defined literal)开释了微小的后劲,这也是本文的重点。 什么是ParserParser是一个解析器函数,输出一个字符串,输入解析后的类型值汇合,函数签名如下: Parser a:: String -> [(a, String)] 简略起见,这里咱们思考只输入零或一个类型值后果,而不是汇合,那么签名如下: Parser a:: String -> Maybe (a, String) 举个例子,一个数字Parser,解析输出字符串"123456",输入后果为Just (1, "23456"),即失去了数字1和残余字符串"23456",从而能够供下一个Parser应用;若解析失败,输入None。 对应C++的函数签名,如下: // Parser a :: String -> Maybe (a, String)using ParserInput = std::string_view;template <typename T>using ParserResult = std::optional<std::pair<T, ParserInput>>;template <typename T>using Parser = auto(*)(ParserInput) -> ParserResult<T>; 这就是Parser的定义了。 依据定义能够实现几个最根本的Parser,例如匹配给定的字符: constexpr auto makeCharParser(char c) { ...

September 19, 2020 · 4 min · jiezi

关于c++:C面向对象继承与多态

前言通过前两篇博文,我曾经将多态的前提条件总结得七七八八了。这一篇开始正式开展讲多态,以及咱们为什么要应用多态。 多态什么是多态援用百度百科的定义: 多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现形式即为多态。援用Charlie Calverts对多态的形容——多态性是容许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就能够依据以后赋值给它的子对象的个性以不同的形式运作(摘自“Delphi4 编程技术底细”)。简略的说,就是一句话:容许将子类类型的指针赋值给父类类型的指针。我的了解是:子类能够通过父类的指针或者援用,调用子类重写父类的虚函数,以达到一个类型多种状态的成果。 这听起来如同没有什么,我能够间接通过子类的对象调用成员函数不就行了,为啥还要舍本逐末将其赋值到一个父类指针再调用呢?起初学习的时候我也不懂为什么,直到起初我遇到了一个很典型的例子才豁然开朗,这个例子我会在上面讲到。 多态的条件后面也零零散散地介绍了C++多态的条件,这里总结一下: 须要有继承须要应用父类的指针或援用父类须要有虚函数,子类要重写父类的虚函数须要上转型是Java多态的条件,C++次要是通过应用父类的指针或者援用来实现的,也能够认为是一种上转型吧。正是因为应用了父类的指针或者援用,才使得他可能调用子类的虚函数,而不是像上一篇的上转型导致的动态绑定,最终调用的是父类的虚函数。咱们通过以下代码来回顾一下: class base {public: virtual void do_something() //有虚函数 { cout << "I'm base class" << endl; }};class derived : public base //有继承{public: void do_something() //子类重写了父类的虚函数 { cout << "I'm derived class" << endl; }};void fun1(base &b) //父类的援用 { b.do_something();}void fun2(base *b) //父类的指针 { b->do_something();}void fun3(base b) { b.do_something();}int main() { derived d; fun1(d); //I'm derived class fun2(&d); //I'm derived class fun3(d); //I'm base class return 0;}fun1()和fun2()实现的过程都是动静绑定的,即运行时才动静确定要调用哪个函数。那他到底是怎么实现的? ...

September 18, 2020 · 2 min · jiezi

关于c++:xmake-v237-发布-新增-tinyc-和-emscripten-工具链支持

xmake 是一个基于 Lua 的轻量级跨平台构建工具,应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门,可能让用户把更多的精力集中在理论的我的项目开发上。 随着 xmake 最近几年一直的迭代倒退,xmake 曾经在 Github 播种 2.9K star,300+ fork,30+ 贡献者,并且解决了 900+ issues,5400+ Commits,沉闷用户也在一直增长。 当初,xmake v2.3.7 版本公布了,在新版本中,咱们次要欠缺了 xmake 本身的稳定性和兼容性,通过两个月的一直迭代,修复了很多用户反馈的各种应用问题,应用体验和稳定性有了很大的晋升。 另外,咱们在这个版本中也新增对 TinyC 和 Emscripten (WebAssembly) 编译工具链的反对。 尤其是针对 windows 平台,咱们提供了额定的 xmake-tinyc 安装包,外面内置了 tinyc 编译器,使得用户能够齐全脱离臃肿的 vs 环境,一键装置,开箱即用,只须要 5M 的安装包即可开发简略的 C 程序,同时还自带了整套 winapi 头文件。 最初,咱们还改良了 trybuild 模式编译,通过 xmake 能够疾速编译 autotools/cmake 保护的第三方我的项目,并且能够疾速对接 android/ios/mingw等穿插编译环境,实现疾速移植编译。 我的项目源码官网文档新个性介绍更加多样的装置形式新版本中,咱们将 xmake 安装包提交到了 windows winget 以及 ubuntu ppa 仓库,咱们能够更加方便快捷地装置 xmake。 Winget 装置winget install xmakeUbuntu PPA 装置sudo add-apt-repository ppa:xmake-io/xmakesudo apt updatesudo apt install xmake当然,咱们还反对很多其余的装置形式,对于其余平台的具体装置形式见:装置文档。 ...

September 18, 2020 · 3 min · jiezi

关于c++:简单桌面

简介简略桌面是一款玲珑便捷的桌面背景管理软件。由编程爱好者集体开发,不收集使用者个人信息、不连贯网络、不弹窗。 下载 性能反对单动态图片及多动态图片轮播(轮播工夫可设置)反对GIF动画背景反对视频背景 (可调节音量)反对背景自定义标签(可调节字体、色彩、地位)阐明简略桌面应用 Qt 开发,在功能完善后将全副开源简略桌面在业余时间开发保护,难免会有稳定性及功能性缺点,遇到应用问题或应用倡议时,欢送反馈:1508539502@qq.com。“简略桌面_应用问题&应用倡议_在频繁操作时会闪退_可复现”展现哔哩哔哩视频展现 待增加性能支持系统音频频谱反对生命时光主题

September 18, 2020 · 1 min · jiezi

关于c++:无栈协程-Rust学习笔记

作者:谢敬伟,江湖人称“刀哥”,20年IT老兵,数据通信网络专家,电信网络架构师,目前任Netwarps开发总监。刀哥在操作系统、网络编程、高并发、高吞吐、高可用性等畛域有多年的实践经验,并对网络及编程等方面的新技术有浓重的趣味。Rust作为一门新兴语言,主打零碎编程。提供了多种编写代码的模式。2019年底正式推出了 async/await语法,标记着Rust也进入了协程时代。上面让咱们来看一看。Rust协程和Go协程到底有什么不同。 有栈协程 vs. 无栈协程协程的需要来自于C10K问题,这里不做更多探讨。晚期解决此类问题的方法是依赖于操作系统提供的I/O复用操作,也就是 epoll/IOCP 多路复用加线程池技术来实现的。实质上这类程序会保护一个简单的状态机,采纳异步的形式编码,音讯机制或者是回调函数。很多用 C/C++ 实现的框架都是这个套路,毛病在于这样的代码个别比较复杂,特地是异步编码加状态机的模式对于程序员是一个很大的挑战。然而从另外一个角度看,合乎人类逻辑思维的操作形式却恰好是同步的。 思考一个web server的场景:每次一个连贯个别是申请下载一些数据,如果能够用一个线程来解决每一次新连贯,那么这个外部的代码逻辑就能够用同步的形式一路写下来:首先接收数据,而后实现HTTP request解析。依据HTTP头部的信息拜访数据库,而后将获得的后果封装在HTTP response中,返回给用户,最初敞开连贯。如果是这样,你会发现这里并不需要状态机,也没有什么回调函数,很可能也不须要定时器,整个的过程就是一个流水账,而这正是人类最容易了解的思维形式。然而,咱们不能简略地用多线程来解决C10K问题,因为操作系统的线程资源是很无限的,而且是低廉的。操作系统会限度能够关上的线程数,同时线程之间的切换开销也是比拟大的。 Go 有栈协程Go语言的呈现提供了一种新的思路。Go语言的协程则相当于提供了一种很低成本的相似于多线程的执行体。在Go语言中,协程的实现与操作系统多线程十分类似。操作系统个别应用抢占的形式来调度零碎中的多线程,而Go语言中,依靠于操作系统的多线程,在运行时刻库中实现了一个合作式的调度器。这里的调度真正实现了上下文的切换,简略地说,Go零碎调用执行时,调度器可能会保留以后执行协程的上下文到堆栈中。而后将以后协程设置为睡眠,转而执行其余的协程。这里须要留神,所谓的Go零碎调用并不是真正的操作系统的零碎调用,而是Go运行时刻库提供的对底层操作系统调用的一个封装。举例说明:Socket recv。咱们晓得这是一个零碎调用,Go的运行时刻库也提供了简直截然不同的调用形式,但这只是建设在 epoll 之上的模仿层,底层的socket是工作在非阻塞的形式,而模仿层提供给咱们了看上去是阻塞模式的socket。读写这个模仿的socket会进入调度器,最终导致协程切换。目前Go调度器实现在用户空间,实质上是一种合作式的调度器。这也是为什么如果写了一个死循环在协程里,则协程永远没有机会被换出,一个Processor相当于就被节约掉了。 有栈的协程和操作系统多线程是很类似的。思考以下伪代码: func routine() int{ var a = 5 sleep(1000) a += 1 return a}sleep调用时,会产生上下文的切换,以后的执行体被挂起,直到约定的工夫再被唤醒。局部变量a 在切换时会被保留在栈中,切换回来后从栈中复原,从而得以持续运行。所谓有栈就是指执行体自身的栈。每次创立一个协程,须要为它调配栈空间。到底调配多大的栈的空间是一个技术活。分的多了,节约,分的少了,可能会溢出。Go在这里实现了一个协程栈扩容的机制,绝对比拟优雅的解决了这个问题。另外一个问题,对于上下文切换,这个别是跟平台或者CPU相干的代码,因为要波及到寄存器操作。同时上下文切换也是有一点代价的,因为毕竟须要额定执行一些指令(集体感觉这一点能够疏忽掉,无栈的协程实现难道不是也须要一些额定的指令来实现程序逻辑的跳转?)。 有栈协程看起来还是比拟直观,特地是对于开发人员比拟敌对。如果比照一下Rust实现的无栈协程,就会晓得因为引入这个栈,保留上下文,从而解决了很多很麻烦的问题。 对于Go,讲一点题外话。 Go有一个比拟宏大的运行时刻库。从上文咱们理解到,因为Go调度器的须要,运行时刻库把所有的零碎调用都做了封装,这些所谓零碎调用都被引入了调度器的调度点,也就是说,执行这类零碎调用会进行协程的上下文切换。所以换一句话说。Go的零碎调用,其实都是被包装过的,可能感知协程的零碎调用。所以从这个角度也能够了解为什么Go的运行时刻库是比拟宏大的。另外,cgo的执行也是相似的过程。因为调用的C代码十分有可能通过C库来执行零碎调用,这样会使线程进入阻塞,从而影响Go的调度器的行为。所以咱们看到cgo总会执行entersyscall和exitsyscall,就是这个起因。 Rust 协程绿色线程 GreenThread晚期的Rust反对一个所谓的绿色线程,其实就是有栈协程的实现,与Go协程实现很类似。在0.7之后,绿色线程就被删除了。其中一个起因是,如果引入这样的机制,那么运行时刻库也必须如Go语言一样可能反对有栈协程,也就是之前探讨Go题外话提到的内容。Go没有Native thread的概念,语言层面只反对协程,抉择封装全副的零碎调用很正当。然而,如果Rust也打算这么做,那么Native thread和协程运行库API对立的问题将很难解决。 无栈协程无栈协程顾名思义就是不应用栈和上下文切换来执行异步代码逻辑的机制。这里异步代码尽管是异步的,但执行起来看起来是一个同步的过程。从这一点上来看Rust协程与Go协程也没什么两样。举例说明: async fn routine() { let mut a = 5; sleep(1000).await; a = a + 1; a}简直是一样的流程。Sleep会导致睡眠,当工夫已到,从新返回执行,局部变量a 内容应该还是5。Go协程是有栈的,所以这个局部变量保留在栈中,而Rust是怎么实现的呢?答案就是 Generator 生成的状态机。Generator 和闭包相似,可能捕捉变量a,放入一个匿名的构造中,在代码中看起来是局部变量的数据 a,会被放入构造,保留在全局(线程)栈中。另外值得一提的是,Generator 生成了一个状态机以保障代码正确的流程。从sleep.await 返回之后会执行 a=a+1 这行代码。async routine() 会依据外部的 .await 调用生成这样的状态机,驱动代码依照既定的流程去执行。 ...

September 15, 2020 · 1 min · jiezi

关于c++:多线程-Rust学习笔记

作者:谢敬伟,江湖人称“刀哥”,20年IT老兵,数据通信网络专家,电信网络架构师,目前任Netwarps开发总监。刀哥在操作系统、网络编程、高并发、高吞吐、高可用性等畛域有多年的实践经验,并对网络及编程等方面的新技术有浓重的趣味。古代的CPU根本都是多核构造,为了充分利用多核的能力,多线程都是绕不开的话题。无论是同步或是异步编程,与多线程相干的问题始终都是艰难并且容易出错的,实质上是因为多线程程序的复杂性,特地是竞争条件的谬误,使得谬误产生具备肯定的随机性,而随着程序的规模越来越大,解决问题的难度也随之越来越高。 其余语言的做法C/C++将同步互斥,以及线程通信的问题全副交给了程序员。要害的共享资源个别须要通过Mutex/Semaphone/CondVariable之类的同步原语保障平安。简略地说,就是须要加锁。然而怎么加,在哪儿加,怎么开释,都是程序员的自在。不加也能跑,绝大多数时候,也不会出问题。当程序的负载上来之后,不经意间程序解体了,而后就是苦楚地寻找问题的过程。 Go提供了通过channel的音讯机制来规范化协程之间的通信,然而对于共享资源,做法与C/C++没有什么不同。当然,遇到的问题也是相似。 Rust 做法与Go相似,Rust 也提出了channel机制用于线程之间的通信。因为Rust 所有权的关系,无奈同时持有多个可变援用,因而channel被分成了rx和tx两局部,应用起来没有Go的那么直观和棘手。事实上,channel的外部实现也是应用原子操作、同步原语对于共享资源的封装。所以,问题的本源仍然在于Rust如何操作共享资源。 Rust 通过所有权以及Type零碎给出了解决问题的一个不同的思路,共享资源的同步与互斥不再是程序员的选项,Rust代码中同步及互斥相干的并发谬误都是编译时谬误,强制程序员在开发时就写出正确的代码,这样远远好过面对在生产环境中顶着压力排查问题的困境。咱们来看一看这所有是如何做到的。 Send,Sync 到底是什么Rust语言层面通过 std::marker 提供了 Send 和 Sync 两个Trait。个别地说法,Send标记表明类型的所有权能够在线程间传递,Sync标记表明一个实现了Sync 的类型能够平安地在多个线程中领有其值的援用。这段话很费解,为了更好地了解Send 和 Sync,须要看一看这两个束缚到底是怎么被应用的。以下是规范库中std::thread::spawn()的实现: pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static, { unsafe { self.spawn_unchecked(f) } }能够看到,创立一个线程,须要提供一个闭包,而这个闭包的束缚是 Send ,也就是须要能转移到线程中,闭包返回值T的束缚也是 Send(这个不难理解,线程运行后返回值须要转移回去) 。举例说明,以下代码无奈通过编译。 let a = Rc::new(100); let h = thread::spawn(move|| { let b = *a+1; }); h.join();编译器指出,std::rc::Rc<i32> cannot be sent between threads safely。起因在于,闭包的实现在外部是由编译器创立一个匿名构造,将捕捉的变量存入此构造。以上代码闭包大抵被翻译成: ...

September 10, 2020 · 1 min · jiezi

关于c++:Essential-C-中文版Chapter4-课后题

4.1 / 4.2stack.h文件 #pragma once #include<string>#include<vector> class Stack {public: bool push(const std::string &); // 参数名能够省略 bool pop(std::string &); bool peek(std::string &); bool empty() { return _stack.size() == 0; } bool full() { // 实际上max_size不肯定代表元素个数肯定能达到这个值 return _stack.size() == _stack.max_size(); } // 如果定义在class自身中, 那么默认为inline函数 int size() { return _stack.size(); } bool find(const std::string &); int count(const std::string &); private: std::vector<std::string> _stack;};stack.cc文件 #include<iostream>#include "stack.h"bool Stack::push(const std::string & ele) { if (full()) { return false; } _stack.push_back(ele); return true;}bool Stack::peek(std::string & ele) { if (empty()) { return false; } ele = _stack.back(); return true;}bool Stack::pop(std::string & ele) { if (empty()) { return false; } ele = _stack.back(); _stack.pop_back(); return true;}bool Stack::find(const std::string & ele) { if (empty()) { return false; } std::vector<std::string>::iterator it = std::find(_stack.begin(), _stack.end(), ele); return it != _stack.end();}int Stack::count(const std::string & ele) { int cnt = 0; if (empty()) { return cnt; } auto it = _stack.begin(); while (true) { it = std::find(it, _stack.end(), ele); if (it != _stack.end()) { cnt++; it++; // 这里肯定要++, 不然会始终循环 } else { break; } } return cnt;}int main() { Stack stack; stack.push("Hello"); stack.push(" "); stack.push("World"); stack.push("Hello"); std::cout << "Find Hello : " << stack.find("Hello") << std::endl; std::cout << "How many times about Hello :" << stack.count("Hello") << std::endl; while (!stack.empty()) { std::string str; stack.pop(str); std::cout << str << std::endl; } return 0;}

September 8, 2020 · 2 min · jiezi

关于c++:最新阿里CC-Linux后台开发面试题及答案

1、Mysql有哪些存储引擎?请具体列举其区别?InnoDB: 事务型存储引擎, 并且有较高的并发读取频率 MEMORY: 存储引擎,寄存在内存中,数据量小, 速度快 Merge: ARCHIVE: 归档, 有很好的压缩机制 2、设计高并发零碎数据库层面该如何设计? 数据库锁有哪些类型?如何实现?1. 分库分表: 同样量的数据均匀存储在不同数据库雷同表(或不同表)中,加重单表压力,如果还是很大,就能够每个库在分多张表,依据hash取值或者其余逻辑判断将数据存储在哪张表中 2. 读写拆散: 数据库本来就有主从数据库之分,查问在从服务器,增删改在主服务器, 3. 归档和操作表辨别: 建一张归档表,将历史数据放入,须要操作的表数据独自存储 4. 索引啊之类的创立,对于数据量很大,百万级别以上的单表,如果增删改操作不频繁的话, 能够创立bitMap索引,速度要快得多 1. 共享锁:要等第一个人操作完,开释锁,能力操作 2. 更新锁:解决死锁,他人能够读,但不能操作 3. 排他锁:读写都被禁用 4. 意向锁(xlock): 对表中局部数据加锁,查问时,能够跳过 5. 打算锁: 操作时,别的表连贯不了这张表 3、讲讲分布式惟一ID?确定ID存储用64位,1个64位二进制1是这样的00000000.....1100......0101,切割64位,某段二进制示意成1个约束条件,前41位为毫秒工夫,后紧接9位为IP,IP之后为自增的二进制,记录当后面位数雷同状况下是第几个id,如当初有10台机器,这个id生成器生成id极限是同台机器1ms内生成2的14次方个ID。 分布式惟一ID = 工夫戳 << 41位, int类型服务器编号 << 10,序列自增sequence。每个工夫戳内只能生成固定数量如(10万)个自增号,达到最大值则同步期待下个工夫戳,自增从0开始。将毫秒数放在最高位,保障生成的ID是趋势递增的,每个业务线、每个机房、每个机器生成的ID都是不同的。如39bit毫秒数|4bit业务线|2bit机房|预留|7bit序列号。高位取2016年1月1日1到当初的毫秒数,零碎运行10年,至多须要10年x365天x24小时x3600秒x1000毫秒=320x10~9,差不多39bit给毫秒数,每秒单机顶峰并发小于100,差不多7bit给每毫秒的自增号,5年内机房小于100台机器,预留2bit给机房,每个机房小于100台机器,预留7bit给每个机房,业务线小于10个,预留4bit给业务线标识。 64bit分布式ID(42bit毫秒+5bit机器ID+12位自增)等 生成分布式ID的形式:A,2个自增表,步长互相隔开 B,工夫的毫秒或者纳秒 C,UUID D,64位约束条件(如上) 4、Redis内存数据回升到肯定大小会执行数据淘汰策略,Redis提供了哪6种数据淘汰策略?LRU:从已设置过期工夫的数据汇合中筛选最近起码应用的数据淘汰 random:从已设置过期工夫的数据中筛选任意数据淘汰 ttl:从已设置过期工夫的数据汇合中筛选将要过期的数据淘汰。 notenvision:禁止驱赶数据 如mysql中有2千万数据,redis只存储20万的热门数据。LRU或者TTL都满足热点数据读取较多,不太可能超时特点。 redis特点:速度块,O(1),丰盛的数据类型,反对事物原子性,可用于缓存,比memecache速度块,能够长久化数据。 常见问题和解决:Master最好不做长久化如RDB快照和AOF日志文件;如果数据比拟重要,某分slave开启AOF备份数据,策略为每秒1次,为了主从复制速度及稳固,MS主从在同一局域网内;主从复制不要用图状构造,用单向链表更为稳固 M-S-S-S-S。。。。;redis过期采纳懒汉+定期,懒汉即get/set时候查看key是否过期,过期则删除key,定期遍历每个DB,查看制订个数个key;联合服务器性能调节并发状况。 过期淘汰,数据写入redis会附带1个无效工夫,这个无效工夫内该数据被认为是正确的并不关怀真实情况,例如对领取等业务采纳版本号实现,redis中每一份数据都维持1个版本号,DB中也维持1份,只有当redis的与DB中的版本统一时,才会认为redis为无效的,不过依然每次都要拜访DB,只须要查问version版本字段即可。 c/c++ linux后盾服务器开发学习地址:https://ke.qq.com/course/4177...(内容包含:C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等等) 5、ZooKeeper分布式是如何做到高可用?ZooKeeper 运行期间,集群中至多有过半的机器保留了最新数据。集群超过半数的机器可能失常工作,集群就可能对外提供服务。 zookeeper能够选出N台机器作主机,它能够实现M:N的备份;keepalive只能选出1台机器作主机,所以keepalive只能实现M:1的备份。 通常有以下两种部署计划:双机房部署(一个稳定性更好、设施更牢靠的机房,这个机房就是次要机房,而另外一个机房则更加便宜一些,例如,对于一个由 7 台机器组成的 ZooKeeper 集群,通常在次要机房中部署 4 台机器,剩下的 3 台机器部署到另外一个机房中);三机房部署(无论哪个机房产生了故障,剩下两个机房的机器数量都超过半数。在三个机房中都部署若干个机器来组成一个 ZooKeeper 集群。假如机器总数为 N,各机房机器数:N1 = (N-1)/2 ,N2=1~(N-N1)/2 ,N3 = N - N1 - N2 )。 ...

September 2, 2020 · 2 min · jiezi

关于c++:2020年9月技术笔记

36W(20200830-20200905)20200831set -e呈现非零值,则退出。 shell 中的 set -e 和 set +e的区别

August 31, 2020 · 1 min · jiezi

关于c++:使用条件变量的那些坑你知道吗

【工夫治理的实质是目标治理,如果咱们想要更好的利用工夫,最先要做的是找到最值得咱们破费工夫的事件,自我学习和精进才是最值得咱们做的有意义的事。】 想必大家开发过程中都会用到多线程,用到多线程基本上都会用到条件变量,你了解的条件变量只是简略的wait和notify吗,最近工作中看共事也都只是简略的应用wait和notify,导致我的项目呈现bug却不知如何fix bug,其实这外面还是有一些坑的,程序喵这里总结给大家。 本文内容简介: 什么是条件变量?条件变量如何应用?如何解决条件变量的信号失落问题?如何解决条件变量的虚伪唤醒问题?条件变量为什么肯定要和锁配合应用?什么是条件变量条件变量是多线程程序中用来实现期待和唤醒逻辑罕用的办法。通常有wait和notify两个动作,wait用于阻塞挂起线程A,直到另一个线程B通过通过notify唤醒线程A,唤醒后线程A会持续运行。 条件变量在多线程中很罕用,在有名的生产者和消费者问题中,消费者如何晓得生成者是否生产出了能够生产的产品,通过while循环不停的去判断是否有可生产的产品?家喻户晓,死循环极其耗费CPU性能,所以须要应用条件变量来阻塞线程,升高CPU占用率。 条件变量的应用拿生产者和消费者问题举例,看上面这段代码: std::mutex mutex;std::condition_variable cv;std::vector<int> vec;void Consume() { std::unique_lock<std::mutex> lock(mutex); cv.wait(lock); std::cout << "consume " << vec.size() << "\n";}void Produce() { std::unique_lock<std::mutex> lock(mutex); vec.push_back(1); cv.notify_all(); std::cout << "produce \n";}int main() { std::thread t(Consume); t.detach(); Produce(); return 0;}本意是消费者线程阻塞,期待生产者生产数据后去告诉消费者线程,这样消费者线程就能够拿到数据去生产。但这里有个问题:如果先执行的Produce(),后执行的Consume(),生产者提前生产出了数据,去告诉消费者,然而此时消费者线程如果还没有执行到wait语句,即线程还没有处于挂起期待状态,线程没有期待此条件变量上,那告诉的信号就失落了,前面Consume()中才执行wait处于期待状态,但此时生产者曾经不会再触发notify,那消费者线程就会始终阻塞上来,呈现bug。如何解决这个问题呢?能够附加一个判断条件,就能够解决这种信号失落问题,见代码: std::mutex mutex;std::condition_variable cv;std::vector<int> vec;void Consumer() { std::unique_lock<std::mutex> lock(mutex); if (vec.empty()) { // 退出此判断条件 cv.wait(lock); } std::cout << "consumer " << vec.size() << "\n";}void Produce() { std::unique_lock<std::mutex> lock(mutex); vec.push_back(1); cv.notify_all(); std::cout << "produce \n";}int main() { std::thread t(Consumer); t.detach(); Produce(); return 0;}通过减少附加条件能够解决信号失落的问题,但这里还有个中央须要留神,消费者线程处于wait阻塞状态时,即便没有调用notify,操作系统也会有一些概率会唤醒处于阻塞的线程,使其继续执行上来,这就是虚伪唤醒问题,当呈现了虚伪唤醒后,消费者线程继续执行,还是没有能够生产的数据,呈现了bug。 那怎么解决虚伪唤醒的问题呢,能够在线程由阻塞状态被唤醒后持续判断附加条件,看是否满足唤醒的条件,如果满足则继续执行,如果不满足,则持续去期待,体现在代码中,行将if判断改为while循环判断,见代码: ...

August 29, 2020 · 1 min · jiezi

关于c++:屏幕共享接入指南

屏幕共享的利用场景泛滥,如: 在线课堂,老师剖析桌面教学科技;在线会议,与会者全屏分享会议内容;在线医疗,议程剖析患者电子病例;近程帮助,近程帮忙其他人解决问题;为了无效解决用户的这些痛点,屏幕共享性能应运而生。新版本的屏幕共享不在利用插件的模式,大家都晓得,在Chrome72版本以前,集成屏幕共享性能必须要集成插件,这无异减少了开发者的难度;国内的网络无法访问谷歌商店,也无奈下载插件,从而导致了该性能处处受限,不被大家所采纳。新版本无需插件,只需简略调用几句代码即可领有屏幕共享性能,屏幕共享还能抉择关上敞开屏幕声音,如果屏幕共享了带声音的多媒体,该性能正合适哦,还有anyRTC的屏幕共享默认不采集音频的,如果想屏幕共享的时候输入音频,记得关上该性能。 上述讲了web端的屏幕共享,上面也介绍下Native端的屏幕共享吧,Windows跟MacOS这里就不多介绍了,调用接口即可,简略不便;Android和iOS应用屏幕共享,必须要关上自定义音视频采集模块,内部采集好音视频,往SDK塞音频、视频流即可。具体可返回查看接口文档。 Web端屏幕共享工作原理Web 端屏幕共享,实际上是通过创立一个屏幕共享的视频轨道对象来实现的。你能够调用 createScreenVideoTrack 办法来创立一个用于屏幕共享的本地视频轨道对象。采集屏幕共享的过程中浏览器会询问须要共享哪些屏幕,依据用户的抉择去获取屏幕信息 在 anyrtc Web SDK 中,一个 ArRTCClient 对象同一时间只能公布一个视频轨道。因而如果你想要在公布屏幕共享的同时,还公布本地摄像头视频轨道,则须要创立两个 ArRTCClient 对象,退出同一频道,一路发送屏幕共享轨道,一路发送摄像头视频轨道。Chrome 屏幕共享咱们以Chrome浏览器为例在 Chrome 上屏幕共享,你可间接调用createScreenVideoTrack。 该性能要求 Chrome 72 或以上版本。如果你应用的软件版本不满足此要求,请应用屏幕共享插件实现在 Chrome 上共享屏幕。ArRTC.createScreenVideoTrack({ // 能够在这里配置编码参数,具体参考 API 文档 encoderConfig: "1080p_1",}).then(localScreenTrack => { /** ... **/});分享音频anyrtc Web SDK 反对在 Windows 平台的 Chrome 浏览器 74 及以上版本同时共享屏幕和本地播放的背景音。你须要在调用 createScreenVideoTrack 办法的withAudio 参数设为 enable。 这样设置后,该办法会返回一个列表,蕴含屏幕共享的视频轨道对象和本地播放背景音的音频轨道对象。 ArRTC.createScreenVideoTrack({ encoderConfig: "1080p_1",}, "auto").then([screenVideoTrack, screenAudioTrack] => { /** ... **/});留神: 应用这个办法后,还须要终端用户在屏幕共享的弹出框上勾选分享音频能力真正失效。如果抉择共享单个利用窗口,无奈分享音频。 同时共享屏幕和开启视频因为一个 ArRTCClient 对象只能发送一路视频轨道,所以如果要在一个发送端同时分享屏幕和开启摄像头视频采集,须要创立两个 ArRTCClient,一路发送屏幕共享轨道,一路发送摄像头轨道。 async function startScreenCall() { const screenClient = ArRTC.createClient({ mode: "rtc", codec: "vp8" }); await screenClient.join("<TOKEN>", "<CHANNEL>"); const screenTrack = await ArRTC.createScreenVideoTrack(); await screenClient.publish(screenTrack); return screenClient;}async function startVideoCall() { const videoClient = ArRTC.createClient({ mode: "rtc", codec: "vp8" }); await videoClient.join("<TOKEN>", "<CHANNEL>"); const videoTrack = await ArRTC.createCameraVideoTrack(); await videoClient.publish(videoTrack); return videoClient;}Promise.all([startScreenCall(), startVideoCall()]).then(() => { /** ... **/ });本人订阅本人,会产生额定的计费,如图: ...

August 28, 2020 · 1 min · jiezi

关于c++:C大学教程

C++大学教程 下载地址 https://pan.baidu.com/s/16SrvAoLslBSeTLnVXIIXjw 扫码上面二维码关注公众号回复 100032获取分享码 本书目录构造如下: 第1章 计算机和C++简介 1.1简介 1.2计算机和互联网在工业和钻研畛域中的利用 1.3硬件和软件 1.4数据的层次结构 1.5机器语言、 汇编语言和高级语言 1.6 C++ 1.7程序设计语言 1.8对象技术介绍 1.9典型的C++程序开发环境 1.10试运行一个C++应用程序 1.11操作系统 1.12互联网和万维网 1.13软件开发的一些要害术语 1.14 C++11和开源的Boost库 1.15与信息技术与时俱进 1.16 Web资源 第2章  C++编程入门、 输出/输入和运算符 2.1简介 2.2第一个C++程序: 输入一行文本 2.3批改第一个C++程序 2.4另一个C++程序: 整数相加 2.5内存的概念 2.6算术运算 2.7判断: 相等运算符和关系运算符 2.8本章小结 第3章 类、 对象和字符串的介绍 3.1简介 3.2定义具备成员函数的类 3.3定义具备形参的成员函数 3.4数据成员、 set成员函数和get成员函数 3.5应用构造函数初始化对象 3.6一个类对应一个独立文件的可复用性 3.7接口与实现的拆散 3.8用set函数确认数据的有效性 3.9本章小结 第4章 管制语句(第I局部)、 赋值、 自增和自减运算符 4.1简介 4.2算法 4.3伪代码 4.4控制结构 4.5 if抉择语句 4.6 if...else双路抉择语句 4.7 while循环语句 4.8算法详述: 计数器管制的循环 4.9算法详述: 标记管制的循环 4.10算法详述: 嵌套的管制语句 4.11赋值运算符 4.12自增和自减运算符 4.13本章小结 ...

August 28, 2020 · 2 min · jiezi

关于c++:C编程思想两卷合订本

C++编程思维(两卷合订本) 下载地址 https://pan.baidu.com/s/1cbz_gjw0aYeW8M8YPmrwtQ 扫码上面二维码关注公众号回复 100031获取分享码 本书目录构造如下: 第1卷 规范C++导引 译者序 3 前言 5 第1章 对象导言 11 1.1 形象的过程 11 1.2 对象有一个接口 12 1.3 实现的暗藏 14 1.4 实现的重用 15 1.5 继承:重用接口 15 1.5.1 is-a 关系和is-like-a 关系 18 1.6 具备多态性的可调换对象 18 1.7 创立和销毁对象 21 1.8 异样解决:应答谬误 22 1.9 剖析和设计 22 1.9.1 第0阶段:制订打算 24 1.9.2 第1阶段:咱们在做什么 24 1.9.3 第2阶段:咱们将如何建设对象 26 1.9.4 第3阶段:创立外围 28 1.9.5 第4阶段:迭代用例 29 1.9.6 第5阶段:进化 29 1.9.7 打算的回报 30 1.10 极限编程 30 1.10.1 先写测试 31 1.10.2 结对编程 32 1.11 为什么C++会胜利 32 1.11.1 一个较好的C 32 1.11.2 连续式的学习过程 33 1.11.3 效率 33 1.11.4 零碎更容易表白和了解 33 1.11.5 尽量应用库 33 1.11.6 利用模板的源代码重用 34 1.11.7 错误处理 34 1.11.8 大型程序设计 34 1.12 为向OOP转变而采取的策略 34 1.12.1 指导方针 35 1.12.2 治理的阻碍 35 1.13 小结 37 第2章 对象的创立与应用 38 2.1 语言的翻译过程 38 2.1.1 解释器 38 2.1.2 编译器 39 2.1.3 编译过程 39 2.2 分段编译工具 40 2.2.1 申明与定义 40 2.2.2 连贯 44 2.2.3 应用库文件 44 2.3 编写第一个C++程序 45 2.3.1 应用iostream类 45 2.3.2 名字空间 46 2.3.3 程序的根本构造 47 2.3.4 “Hello, World!” 47 2.3.5 运行编译器 48 2.4 对于输入输出流 48 2.4.1 字符数组的拼接 49 2.4.2 读取输出数据 49 2.4.3 调用其余程序 50 2.5 字符串简介 50 2.6 文件的读写 51 2.7 vector简介 52 2.8 小结 55 2.9 练习 56 第3章 C++中的C 57 3.1 创立函数 57 3.1.1 函数的返回值 58 3.1.2 应用C的函数库 59 3.1.3 通过库管理器创立本人的库 59 3.2 执行管制语句 60 3.2.1 真和假 60 3.2.2 if-else语句 60 3.2.3 while语句 61 3.2.4 do-while语句 61 3.2.5 for语句 62 3.2.6 关键字break 和 continue 63 3.2.7 switch语句 64 3.2.8 应用和滥用goto 65 3.2.9 递归 65 3.3 运算符简介 66 3.3.1 优先级 66 3.3.2 自增和自减 67 3.4 数据类型简介 67 3.4.1 根本内建类型 67 3.4.2 bool类型与true和false 68 3.4.3 说明符 69 3.4.4 指针简介 70 3.4.5 批改内部对象 72 3.4.6 C++援用简介 74 3.4.7 用指针和援用作为修饰符 75 3.5 作用域 76 3.5.1 实时定义变量 77 3.6 指定存储空间调配 78 3.6.1 全局变量 78 3.6.2 局部变量 79 3.6.3 动态变量 80 3.6.4 内部变量 81 3.6.5 常量 82 3.6.6 volatile变量 83 3.7 运算符及其应用 83 3.7.1 赋值 83 3.7.2 数学运算符 83 3.7.3 关系运算符 85 3.7.4 逻辑运算符 85 3.7.5 位运算符 85 3.7.6 移位运算符 86 3.7.7 一元运算符 88 3.7.8 三元运算符 88 3.7.9 逗号运算符 89 3.7.10 应用运算符时的常见问题 89 3.7.11 转换运算符 90 3.7.12 C++的显式转换 90 3.7.13 sizeof—独立运算符 93 3.7.14 asm 关键字 94 3.7.15 显式运算符 94 3.8 创立复合类型 94 3.8.1 用typedef命名别名 95 3.8.2 用struct把变量联合在一起 95 3.8.3 用enum进步水平清晰度 97 3.8.4 用union节俭内存 98 3.8.5 数组 99 3.9 调试技巧 106 3.9.1 调试标记 106 3.9.2 把变量和表达式转换成字符串 108 3.9.3 C语言assert( )宏 108 3.10 函数地址 109 3.10.1 定义函数指针 109 3.10.2 简单的申明和定义 109 3.10.3 应用函数指针 110 3.10.4 指向函数的指针数组 111 3.11 make:治理分段编译 111 3.11.1 make的行为 112 3.11.2 本书中的makefile 114 3.11.3 makefile的一个例子 114 3.12 小结 116 3.13 练习 116 第4章 数据抽象 119 4.1 一个袖珍C库 119 4.1.1 动态存储分配 122 4.1.2 无害的猜想 124 4.2 哪儿出问题 125 4.3 根本对象 126 4.4 什么是对象 130 4.5 抽象数据类型 131 4.6 对象细节 131 4.7 头文件模式 132 4.7.1 头文件的重要性 132 4.7.2 屡次申明问题 133 4.7.3 预处理器批示#define、#ifdef 和#endif 134 4.7.4 头文件的规范 134 4.7.5 头文件中的名字空间 135 4.7.6 在我的项目中应用头文件 135 4.8 嵌套构造 136 4.8.1 全局作用域解析 138 4.9 小结 139 4.10 练习 139 第5章 暗藏实现 142 5.1 设置限度 142 5.2 C++的访问控制 142 5.2.1 protected说明符 144 5.3 友元 144 5.3.1 嵌套友元 146 5.3.2 它是纯面向对象的吗 148 5.4 对象布局 148 5.5 类 149 5.5.1 用访问控制来批改Stash 151 5.5.2 用访问控制来批改Stack 151 5.6 句柄类 152 5.6.1 暗藏实现 152 5.6.2 缩小反复编译 152 5.7 小结 154 5.8 练习 154 第6章 初始化与革除 156 6.1 用构造函数确保初始化 156 6.2 用析构函数确保革除 157 6.3 革除定义块 159 6.3.1 for循环 160 6.3.2 内存调配 161 6.4 带有构造函数和析构函数的Stash 162 6.5 带有构造函数和析构函数的Stack 164 6.6 聚合初始化 166 6.7 默认构造函数 168 6.8 小结 169 6.9 练习 169 第7章 函数重载与默认参数 171 7.1 名字润饰 172 7.1.1 用返回值重载 172 7.1.2 类型平安连贯 172 7.2 重载的例子 173 7.3 联结 176 7.4 默认参数 178 7.4.1 占位符参数 179 7.5 抉择重载还是默认参数 180 7.6 小结 183 7.7 练习 183 第8章 常量 185 8.1 值代替 185 8.1.1 头文件里的const 186 8.1.2 const的安全性 186 8.1.3 聚合 187 8.1.4 与C语言的区别 187 8.2 指针 188 8.2.1 指向const的指针 189 8.2.2 const指针 189 8.2.3 赋值和类型查看 190 8.3 函数参数和返回值 191 8.3.1 传递const值 191 8.3.2 返回const值 191 8.3.3 传递和返回地址 193 8.4 类 195 8.4.1 类里的const 196 8.4.2 编译期间类里的常量 198 8.4.3 const对象和成员函数 200 8.5 volatile 204 8.6 小结 205 8.7 练习 205 第9章 内联函数 207 9.1 预处理器的缺点 207 9.1.1 宏和拜访 209 9.2 内联函数 210 9.2.1 类外部的内联函数 210 9.2.2 拜访函数 211 9.3 带内联函数的Stash和Stack 215 9.4 内联函数和编译器 218 9.4.1 限度 219 9.4.2 向前援用 219 9.4.3 在构造函数和析构函数里暗藏行为 220 9.5 缩小凌乱 220 9.6 预处理器的更多特色 221 9.6.1 标记粘贴 222 9.7 改良的谬误查看 222 9.8 小结 225 9.9 练习 225 第10章 名字管制 227 10.1 来自C语言中的动态元素 227 10.1.1 函数外部的动态变量 227 10.1.2 管制连贯 230 10.1.3 其余存储类型说明符 232 10.2 名字空间 232 10.2.1 创立一个名字空间 232 10.2.2 应用名字空间 234 10.2.3 名字空间的应用 237 10.3 C++中的动态成员 238 10.3.1 定义静态数据成员的存储 238 10.3.2 嵌套类和部分类 241 10.3.3 动态成员函数 242 10.4 动态初始化的相依性 244 10.4.1 怎么办 245 10.5 代替连贯阐明 250 10.6 小结 250 10.7 练习 251 第11章 援用和拷贝构造函数 254 11.1 C++中的指针 254 11.2 C++中的援用 254 11.2.1 函数中的援用 255 11.2.2 参数传递准则 257 11.3 拷贝构造函数 257 11.3.1 按值传递和返回 257 11.3.2 拷贝构造函数 261 11.3.3 默认拷贝构造函数 265 11.3.4 代替拷贝构造函数的办法 266 11.4 指向成员的指针 267 11.4.1 函数 269 11.5 小结 271 11.6 练习 271 第12章 运算符重载 274 12.1 两个极其 274 12.2 语法 274 12.3 可重载的运算符 275 12.3.1 一元运算符 276 12.3.2 二元运算符 279 12.3.3 参数和返回值 288 12.3.4 不罕用的运算符 290 12.3.5 不能重载的运算符 295 12.4 非成员运算符 296 12.4.1 基本方针 297 12.5 重载赋值符 297 12.5.1 operator=的行为 298 12.6 主动类型转换 306 12.6.1 构造函数转换 306 12.6.2 运算符转换 307 12.6.3 类型转换例子 309 12.6.4 主动类型转换的缺点 310 12.7 小结 312 12.8 练习 312 第13章 动静对象创立 315 13.1 对象创立 315 13.1.1 C从堆中获取存储单元的办法 316 13.1.2 operator new 317 13.1.3 operator delete 317 13.1.4 一个简略的例子 318 13.1.5 内存治理的开销 318 13.2 从新设计后面的例子 319 13.2.1 应用delete void*可能会出错 319 13.2.2 对指针的革除责任 320 13.2.3 指针的Stash 320 13.3 用于数组的new和delete 324 13.3.1 使指针更像数组 325 13.4 耗尽内存 325 13.5 重载new和delete 326 13.5.1 重载全局new和delete 327 13.5.2 对于一个类重载new和delete 328 13.5.3 为数组重载new和delete 330 13.5.4 结构函数调用 332 13.5.5 定位new和delete 333 13.6 小结 334 13.7 练习 334 第14章 继承和组合 336 14.1 组合语法 336 14.2 继承语法 337 14.3 构造函数的初始化表达式表 339 14.3.1 成员对象初始化 339 14.3.2 在初始化表达式表中的内建类型 339 14.4 组合和继承的联结 340 14.4.1 构造函数和析构函数调用的秩序 341 14.5 名字暗藏 343 14.6 非主动继承的函数 346 14.6.1 继承和动态成员函数 349 14.7 组合与继承的抉择 349 14.7.1 子类型设置 350 14.7.2 公有继承 352 14.8 protected 353 14.8.1 protected继承 353 14.9 运算符的重载与继承 353 14.10 多重继承 355 14.11 渐增式开发 355 14.12 向上类型转换 356 14.12.1 为什么要“向上类型转换” 357 14.12.2 向上类型转换和拷贝构造函数 357 14.12.3 组合与继承(再论) 359 14.12.4 指针和援用的向上类型转换 360 14.12.5 危机 360 14.13 小结 361 14.14 练习 361 第15章 多态性和虚函数 364 15.1 C++程序员的演变 364 15.2 向上类型转换 365 15.3 问题 366 15.3.1 函数调用捆绑 366 15.4 虚函数 366 15.4.1 扩展性 367 15.5 C++如何实现晚捆绑 369 15.5.1 寄存类型信息 370 15.5.2 虚函数性能图示 371 15.5.3 撩开面纱 372 15.5.4 装置vpointer 373 15.5.5 对象是不同的 373 15.6 为什么须要虚函数 374 15.7 形象基类和纯虚函数 375 15.7.1 纯虚定义 378 15.8 继承和VTABLE 378 15.8.1 对象切片 380 15.9 重载和从新定义 382 15.9.1 变量返回类型 383 15.10 虚函数和构造函数 385 15.10.1 结构函数调用秩序 385 15.10.2 虚函数在构造函数中的行为 386 15.11 析构函数和虚构析构函数 386 15.11.1 纯虚析构函数 388 15.11.2 析构函数中的虚机制 389 15.11.3 创立基于对象的继承 390 15.12 运算符重载 392 15.13 向下类型转换 394 15.14 小结 396 15.15 练习 397 第16章 模板介绍 400 16.1 容器 400 16.1.1 容器的需要 401 16.2 模板综述 402 16.2.1 模板办法 403 16.3 模板语法 404 16.3.1 非内联函数定义 405 16.3.2 作为模板的IntStack 406 16.3.3 模板中的常量 408 16.4 作为模板的Stash和Stack 409 16.4.1 模板化的指针Stash 411 16.5 关上和敞开所有权 415 16.6 以值寄存对象 417 16.7 迭代器简介 418 16.7.1 带有迭代器的栈 425 16.7.2 带有迭代器的PStash 427 16.8 为什么应用迭代器 432 16.8.1 函数模板 434 16.9 小结 435 16.10 练习 435 附录A 编码格调 附录B 编程准则 附录C 举荐读物 第2卷 实用编程技术 译者序 441 前言 442 第一局部 建设稳固的零碎 第1章 异样解决 448 1.1 传统的错误处理 448 1.2 抛出异样 450 1.3 捕捉异样 451 1.3.1 try块 451 1.3.2 异样处理器 451 1.3.3 终止和复原 452 1.4 异样匹配 453 1.4.1 捕捉所有异样 454 1.4.2 从新抛出异样 454 1.4.3 不捕捉异样 455 1.5 清理 456 1.5.1 资源管理 457 1.5.2 使所有事物都成为对象 458 1.5.3 auto_ptr 460 1.5.4 函数级的try块 461 1.6 规范异样 462 1.7 异样规格阐明 464 1.7.1 更好的异样规格阐明 467 1.7.2 异样规格阐明和继承 467 1.7.3 什么时候不应用异样规格阐明 468 1.8 异样平安 468 1.9 在编程中应用异样 471 1.9.1 什么时候防止异样 471 1.9.2 异样的典型利用 472 1.10 应用异样造成的开销 474 1.11 小结 476 1.12 练习 476 第2章 防御性编程 478 2.1 断言 480 2.2 一个简略的单元测试框架 482 2.2.1 自动测试 483 2.2.2 TestSuite框架 485 2.2.3 测试套件 488 2.2.4 测试框架的源代码 489 2.3 调试技术 493 2.3.1 用于代码跟踪的宏 494 2.3.2 跟踪文件 494 2.3.3 发现内存透露 495 2.4 小结 499 2.5 练习 500 第二局部 规范C++库 第3章 深刻了解字符串 504 3.1 字符串的外部是什么 504 3.2 创立并初始化C++字符串 505 3.3 对字符串进行操作 508 3.3.1 追加、插入和连贯字符串 508 3.3.2 替换字符串中的字符 509 3.3.3 应用非成员重载运算符连贯 512 3.4 字符串的查找 513 3.4.1 反向查找 516 3.4.2 查找一组字符第1次或最初一次呈现的地位 517 3.4.3 从字符串中删除字符 519 3.4.4 字符串的比拟 520 3.4.5 字符串和字符的个性 523 3.5 字符串的利用 527 3.6 小结 531 3.7 练习 531 第4章 输入输出流 534 4.1 为什么引入输入输出流 534 4.2 救助输入输出流 537 4.2.1 插入符和提取符 537 4.2.2 通常用法 540 4.2.3 按行输出 541 4.3 解决流谬误 542 4.4 文件输入输出流 544 4.4.1 一个文件解决的例子 544 4.4.2 关上模式 546 4.5 输入输出流缓冲 546 4.6 在输入输出流中定位 548 4.7 字符串输入输出流 550 4.7.1 输出字符串流 551 4.7.2 输入字符串流 552 4.8 输入流的格式化 555 4.8.1 格式化标记 555 4.8.2 格式化域 556 4.8.3 宽度、填充和精度设置 557 4.8.4 一个残缺的例子 557 4.9 操纵算子 560 4.9.1 带参数的操纵算子 560 4.9.2 创立操纵算子 562 4.9.3 效用算子 563 4.10 输入输出流程序举例 565 4.10.1 保护类库的源代码 565 4.10.2 检测编译器谬误 568 4.10.3 一个简略的数据记录器 570 4.11 国际化 573 4.11.1 宽字符流 574 4.11.2 区域性字符流 575 4.12 小结 577 4.13 练习 577 第5章 深刻了解模板 580 5.1 模板参数 580 5.1.1 无类型模板参数 580 5.1.2 默认模板参数 582 5.1.3 模板类型的模板参数 583 5.1.4 typename关键字 587 5.1.5 以template关键字作为提醒 588 5.1.6 成员模板 589 5.2 无关函数模板的几个问题 591 5.2.1 函数模板参数的类型推断 591 5.2.2 函数模板重载 594 5.2.3 以一个已生成的函数模板地址作为参数 595 5.2.4 将函数利用到STL序列容器中 598 5.2.5 函数模板的半有序 600 5.3 模板特化 601 5.3.1 显式特化 601 5.3.2 半特化 602 5.3.3 一个实例 604 5.3.4 避免模板代码收缩 606 5.4 名称查找问题 609 5.4.1 模板中的名称 609 5.4.2 模板和友元 613 5.5 模板编程中的习语 617 5.5.1 特色 617 5.5.2 策略 621 5.5.3 奇异的递归模板模式 623 5.6 模板元编程 624 5.6.1 编译时编程 625 5.6.2 表达式模板 631 5.7 模板编译模型 636 5.7.1 蕴含模型 636 5.7.2 显式实例化 637 5.7.3 拆散模型 638 5.8 小结 639 5.9 练习 640 第6章 通用算法 642 6.1 概述 642 6.1.1 断定函数 644 6.1.2 流迭代器 646 6.1.3 算法复杂性 647 6.2 函数对象 648 6.2.1 函数对象的分类 649 6.2.2 主动创立函数对象 649 6.2.3 可调整的函数对象 652 6.2.4 更多的函数对象例子 653 6.2.5 函数指针适配器 658 6.2.6 编写本人的函数对象适配器 662 6.3 STL算法目录 665 6.3.1 实例创立的反对工具 666 6.3.2 填充和生成 669 6.3.3 计数 670 6.3.4 操作序列 671 6.3.5 查找和替换 674 6.3.6 比拟范畴 679 6.3.7 删除元素 681 6.3.8 对已排序的序列进行排序和运算 684 6.3.9 堆运算 691 6.3.10 对某一范畴内的所有元素进行运算 691 6.3.11 数值算法 697 6.3.12 通用实用程序 699 6.4 创立本人的STL格调算法 700 6.5 小结 701 6.6 练习 702 第7章 通用容器 706 7.1 容器和迭代器 706 7.2 概述 707 7.2.1 字符串容器 711 7.2.2 从STL容器继承 712 7.3 更多迭代器 714 7.3.1 可逆容器中的迭代器 715 7.3.2 迭代器的品种 716 7.3.3 预约义迭代器 717 7.4 根本序列容器:vector、list和deque 721 7.4.1 根本序列容器的操作 721 7.4.2 向量 723 7.4.3 双端队列 728 7.4.4 序列容器间的转换 730 7.4.5 被查看的随机拜访 731 7.4.6 链表 732 7.4.7 替换序列 736 7.5 汇合 737 7.6 堆栈 743 7.7 队列 745 7.8 优先队列 748 7.9 持有二进制位 755 7.9.1 bitset<n> 756 7.9.2 vector<bool> 758 7.10 关联式容器 760 7.10.1 用于关联式容器的发生器和填充器 763 7.10.2 不堪设想的映像 765 7.10.3 多重映像和反复的关键字 766 7.10.4 多重汇合 768 7.11 将STL容器联结应用 771 7.12 革除容器的指针 773 7.13 创立本人的容器 774 7.14 对STL的裁减 776 7.15 非STL容器 777 7.16 小结 781 7.17 练习 781 第三局部 专 题 第8章 运行时类型辨认 785 8.1 运行时类型转换 785 8.2 typeid 操作符 789 8.2.1 类型转换到两头档次类型 790 8.2.2 void型指针 791 8.2.3 使用带模板的RTTI 792 8.3 多重继承 793 8.4 正当应用RTTI 793 8.5 RTTI的机制和开销 797 8.6 小结 797 8.7 练习 798 第9章 多重继承 800 9.1 概论 800 9.2 接口继承 801 9.3 实现继承 803 9.4 重复子对象 807 9.5 虚基类 810 9.6 名字查找问题 817 9.7 防止应用多重继承 819 9.8 裁减一个接口 820 9.9 小结 823 9.10 练习 823 第10章 设计模式 825 10.1 模式的概念 825 10.2 模式分类 826 10.3 简化习语 827 10.3.1 信使 827 10.3.2 收集参数 828 10.4 单件 829 10.5 命令:抉择操作 833 10.6 打消对象耦合 836 10.6.1 代理模式:作为其余对象的前端 837 10.6.2 状态模式:扭转对象的行为 838 10.7 适配器模式 840 10.8 模板办法模式 841 10.9 策略模式:运行时抉择算法 842 10.10 职责链模式:尝试采纳一系列 策略模式 843 10.11 工厂模式:封装对象的创立 845 10.11.1 多态工厂 847 10.11.2 形象工厂 849 10.11.3 虚构造函数 851 10.12 构建器模式:创立简单对象 855 10.13 观察者模式 860 10.13.1 “外部类”办法 862 10.13.2 观察者模式举例 864 10.14 多重差遣 867 10.15 小结 873 10.16 练习 873 第11章 并发 875 11.1 动机 875 11.2 C++中的并发 876 11.3 定义工作 878 11.4 应用线程 879 11.4.1 创立有响应的用户界面 880 11.4.2 应用执行器简化工作 882 11.4.3 退让 884 11.4.4 休眠 885 11.4.5 优先权 886 11.5 共享无限资源 887 11.5.1 保障对象的存在 887 11.5.2 不恰当地拜访资源 890 11.5.3 访问控制 892 11.5.4 应用爱护简化编码 893 11.5.5 线程本地存储 896 11.6 终止工作 897 11.6.1 避免输出/输入流抵触 897 11.6.2 举例观赏植物园 898 11.6.3 阻塞时终止 901 11.6.4 中断 902 11.7 线程间合作 906 11.7.1 期待和信号 906 11.7.2 生产者-消费者关系 909 11.7.3 用队列解决线程解决的问题 912 11.7.4 播送 916 11.8 死锁 921 11.9 小结 925 11.10 练习 926 ...

August 27, 2020 · 10 min · jiezi

关于c++:C编程规范101条规则准则与最佳实践

C++编程标准-101条规定准则与最佳实际 下载地址 https://pan.baidu.com/s/1jJfO2W9mf16d7KqwbPJBrQ 扫码上面二维码关注公众号回复 100030获取分享码 本书目录构造如下: 组织和策略问题 1 第0条 不要拘泥于大节(又名:理解哪些货色不应该标准化) 2 第 1条 在高正告级别干净利落地进行编译 4 第 2条 应用主动构建零碎 7 第3条 应用版本控制系统 8 第4条 做代码审查 9设计格调 11 第5条 一个实体应该只有一个紧凑的职责 12 第6条 正确、简略和清晰第 一 13 第7条 编程中应晓得何时和如何思考可伸缩性 14 第8条 不要进行不成熟的优化 16 第9条 不要进行不成熟的劣化 18 第 10条 尽量减少全局和共享数据 19 第 11条 暗藏信息 20 第 12条 懂得何时和如何进行并发性编程 21 第 13条 确保资源为对象所领有。应用显式的RAII和智能指针 24 编程格调 27 第 14条 宁要编译时和连贯时谬误,也不要运行时谬误 28 第 15条 踊跃应用const 30 第 16条 防止应用宏 32 ...

August 27, 2020 · 2 min · jiezi

关于c++:C-Primer中文版-第5版

C++  Primer中文版  第5版 下载地址 https://pan.baidu.com/s/1X1coefIGxZfKML04335I0A 扫码上面二维码关注公众号回复 100028获取分享码 本书目录构造如下: 第1章 开始1 1.1 编写一个简略的c++程序2 1.1.1 编译、运行程序3 1.2 初识输入输出5 1.3 正文简介8 1.4 控制流10 1.4.1 while语句10 1.4.2 for语句11 1.4.3 读取数量不定的输出数据13 1.4.4 if语句15 1.5 类简介17 1.5.1 sales_item类17 1.5.2 初识成员函数20 1.6 书店程序21 小结23 术语表23 第ⅰ局部 c++根底27 第2章 变量和根本类型29 2.1 根本内置类型30 .2.1.1 算术类型30 2.1.2 类型转换32 2.1.3 字面值常量35 2.2 变量38 2.2.1 变量定义38 2.2.2 变量申明和定义的关系41 2.2.3 标识符42 2.2.4 名字的作用域43 2.3 复合类型45 2.3.1 援用45 2.3.2 指针47 ...

August 27, 2020 · 5 min · jiezi

关于c++:c进阶Compare

数学中关系的定义:https://baike.baidu.com/item/%E5%85%B3%E7%B3%BB/3785874?fr=aladdin关系是有序对的汇合 关系可能具备的性质定义以下均假如R是汇合A上的二元关系: 自反性 ,如果对于A中的每个元素x,都有<x, x> 属于R,则称R具备自反性。反自反性(irreflexivity) ,如果对于A中每个元素x,都有<x, x>不属于R,则称R具备反自反性。对称性,如果对于R中的每个有序对<x, y>都有对应的有序对<y, x>也属于关系R,则称R具备对称性。反对称性,如果对于R中的每个有序对<x, y>,且<y, x>也属于关系R,那么x == y肯定成立,则称R具备反对称性。留神:有些关系既是对称的,又是拥护称的,如相等关系;有些关系是对称的,但不是拥护称的,如Z中的“绝对值相等”;有些关系是拥护称的,但不是对称的,如Z中的≤和<;还有的关系既不是对称的,又不是拥护称的。传递性 对于A中的元素x, y, z, 如果<x, y>属于R并且<y, z>属于R,那么<x, z>就属于R,则称R具备传递性。偏序集(partical order)设R是汇合A上的一个关系,如果R是自反的、拥护称的和可传递的,则称R是汇合A的偏序关系,简称偏序,记作“≤”。这里的符号不仅仅指咱们之前学过的具体符号,而是偏序的符号,当然小于等于号(对应的关系)自身是典型的偏序关系。个别将一个汇合A和定义在其上的偏序关系R一起称为偏序集。wiki定义:https://en.wikipedia.org/wiki/Partially_ordered_set#Strict_and_non-strict_partial_orders对于汇合A中的元素x和y而言,如果有序对<x, y>或者<y, x>属于偏序关系R,则称x和y是可比拟的(comparable),否则称x和y是不可比拟的(incomparable)。如果汇合A中的任意两个元素之间是可比拟的,则称偏序关系R为全序关系(total order)。 全序集(total order)对于一个偏序集A,R,如果对于A中的任意两个元素x和y,有序对<x, y>和<y, x>至多有一个属于关系R,则称R为序关系,A和R一起称为全序集合/有序集。和下面的定义实质上是一样的。 举例:一个偏序集而不是全序集的例子,汇合的蕴含关系,两个汇合间可能是不可比拟的。 严格和非严格偏序关系(strict and non-strict partial orders)上述定义的偏序集能够认为是非严格的,次要是为了与上面的严格偏序集做比照:一个严格偏序关系须要具备如下性质:反自反性,传递性和反对称性。记作小于号符号,和下面的定义相似,这里仅作为一个符号应用,当然咱们相熟的小于号对应的关系是典型的严格偏序关系。 严格的弱序关系(strict weak orderings)如果一个严格偏序集(汇合A与定义在汇合A上的严格偏序关系R)的关系R满足:如果A上的元素x,y,z,x和y是不可比拟的,y和z是不可比拟的,则x和z是不可比拟的。那么称这样的关系为严格弱序关系,也就是说具备可传递的不可比拟性。 等价关系(equivalence relation)一个等价关系应该具备如下性质:自反性,传递性,对称性。留神到,严格弱序集上的不可比拟的关系(incomparability relation)是一种等价关系。 // 集体猜想,官网说法很含糊。证实://留神了解,不可比拟关系是依附于某个关系定义的,即是关系的关系。//自反性:x和x是不可比拟的,因为严格弱序是反自反的,所以!(xRx) && !(xRx)为真。//传递性:!(xRy) && !(yRx)为真,!(yRz) && !(zRy)为真,则因为严格弱序关系的额定性质,即可传递的不可比拟性,因而!(xRz) && !(zRx)为真,不可比拟关系是传递的//对称性:!(xRy) && !(yRx)为真,则因为逻辑运算左右两侧替换不影响后果,因而不可比拟关系是对称的。所以说严格弱序关系的定义保障了定义在其上的不可比拟关系是等价关系。wiki : https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings 以上是前导常识,当初看下明天要说的c++中的一个concept:Compare。这个concept在c++的规范库中宽泛波及并应用,例如关联容器set和map中,算法sort中等等,url : https://en.cppreference.com/w/cpp/named_req/Compare具体的requirements见上链接即可,总的来说就是满足Compare的类的对象是一个函数对象,等同于关系,其两个参数等同于元素,这个关系应该是一个严格弱序关系。 留神规范中的这句话:Note: comp induces a strict total ordering on the equivalence classes determined by equiv这个严格弱序关系在equiv定义的等价类上是一个严格全序关系//equiv就是上文中的不可比拟关系(也是等价关系),原汇合能够被划分为不同的等价类,每个等价类是一个子集合,该汇合中的元素两两等价。这其实很好了解,只有x和y来自不同的等价类,那么<x, y>或者<y, x>至多有一个属于严格弱序关系的汇合--因为依据定义都不属于的话x和y必定在一个等价类中。 ...

August 25, 2020 · 1 min · jiezi

关于c++:linux-c编程之高效线程池如何实现无琐化

大多数线程池实现都离不开锁的应用,如互斥量pthread_mutex*联合条件变量pthread_cond*。家喻户晓,锁的应用对于程序性能影响较大,尽管现有的pthread_mutex*在锁的申请与开释方面做了较大的优化,然而,线程池的实现是能够做到无锁化的。 1.常见线程池实现原理 如上图所示,工作队列由主线程和工作者线程共享,主线程将工作放进工作队列,工作者线程从工作队列中取出工作执行。共享工作队列的操作需在互斥量的爱护下平安进行,主线程将工作放进工作队列时若检测到以后待执行的工作数目小于工作者线程总数,则需应用条件变量唤醒可能处于期待状态的工作者线程。当然,还有其余中央可能也会应用到互斥量和条件变量,不再赘述。 2.无锁化线程池实现原理 为解决无锁化的问题,须要防止共享资源的竞争,因而将共享工作队列加以拆分成每工作线程一个工作队列的形式。对于主线程放入工作和工作线程取出工作的竞争问题,能够采取环形队列的形式防止。在解决了锁机制之后,就只剩下条件变量的问题了,条件变量自身即解决条件满足时的线程通信问题,而信号作为一种通信形式,能够代替之,其大体编程范式为: sigemptyset (&oldmask);sigemptyset (&signal_mask);sigaddset (&signal_mask, SIGUSR1);rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);if (rc != 0) { debug(TPOOL_ERROR, "SIG_BLOCK failed"); return -1;}...while (!condition) { rc = sigwait (&signal_mask, NULL); if (rc != 0) { debug(TPOOL_ERROR, "sigwait failed"); return -1; }}rc = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);if (rc != 0) { debug(TPOOL_ERROR, "SIG_SETMASK failed"); return -1;}须要C/C++ Linux服务器架构师学习材料加qun(563998835)(材料包含C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),收费分享 3.无锁化线程池具体实现在无锁线程池中,区别于常见线程池的中央次要在于信号与条件变量、任务调度算法、减少或缩小线程数目后的工作迁徙,另外还有一点就是环形队列的实现参考了Linux内核中的kfifo实现。 (1) 信号与条件变量 信号与条件变量的区别次要在于条件变量的唤醒(signal)对于接管线程而言能够疏忽,而在未设置信号处理函数的状况下信号的接管会导致接管线程甚至整个程序的终止,因而须要在线程池产生线程之前指定信号处理函数,这样新生的线程会继承这个信号处理函数。多线程中信号的发送次要采纳pthread_kill,为防止应用其余信号,本程序中应用了SIGUSR1。 (2) 任务调度算法 常见线程池实现的任务调度次要在操作系统一级通过线程调度实现。思考到负载平衡,主线程放入工作时应采取适合的任务调度算法将工作放入对应的工作者线程队列,本程序目前已实现Round-Robin和Least-Load算法。Round-Robin即轮询式地调配工作,Least-Load即抉择以后具备起码工作的工作者线程放入。 (3) 工作迁徙 在线程的动静减少和缩小的过程中,同样基于负载平衡的考量,波及到现有工作的迁徙问题。负载平衡算法次要基于均匀工作量的思维,即统计以后时刻的总任务数目,均分至每一个线程,求出每个工作者线程应该减少或缩小的工作数目,而后从头至尾遍历,须要移出工作的线程与须要移入工作的线程执行工作迁徙,互相对消。最初若还有多进去的工作,再顺次调配。迁入工作不存在竞态,因为退出工作始终由主线程实现,而迁出工作则存在竞态,因为在迁出工作的同时工作者线程可能在同时执行工作。所以须要采纳原子操作加以修改,其次要思维即预取技术,大抵实现为: ...

August 24, 2020 · 1 min · jiezi

关于c++:C语言中的字符串处理库函数介绍与实现

strlen函数:求字符串的长度size_t strlen(const char *s)头文件:#include<string.h>阐明:求出s指向的字符串的长度(不包含null字符)。返回值:返回s指向的字符串的长度。size_t strlen(const char *s){ size_t len = 0; while(*s++) len++; return len;}strcpy和strncpy函数:复制字符串char strcpy(char s1,const char *s2)头文件:#include<string.h>阐明:将s2指向的字符串复制到s1指向的数组中。若s1和s2指向的内存空间重叠,则作未定义解决。返回值:返回s1的值。char *strcpy(char *s1,const char *s2){ char *tmp = s1; while(*s1++ = *s2++) ; return tmp;}char strncpy(char s1,const char *s2,size_t n);头文件:#include<string.h>阐明:将s2指向的字符串复制到s1指向的数组中。若s2的长度大于等于n,则复制到第n个字符为止。否则用null字符填充残余局部。若s1和s2指向的内存空间重叠,则作未定义解决。返回值:返回s1的值。char *strncpy(char *s1,const char *s2,size_t n){ char *tmp = s1; while(n){ if(!(*s1++ = *s2++)) break; //遇到'\0'就完结循环 n--; } while(n--) *s1++ = '\0'; //用'\0'填充残余局部 return tmp; }strcat和strncat函数:连贯字符串char *strcat(char *s1,const char *s2)头文件:#include<string.h>阐明:将s2指向的字符串连贯到s1指向的开端。若s1和s2指向的内存空间重叠,则作未定义解决返回值:返回s1的值。char *strcat(char *s1,const char *s2){ char *tmp = s1; while(*s1) s1++; //后退到s1的开端处 while(*s1++ = *s2++) ; //循环复制直至遇到s2中的'\0' return tmp;}char *strncat(char *s1,const char *s2,size_t n);头文件:#include<string.h>阐明:将s2指向的字符串连贯到s1指向的数组开端。若s2的长度大于n则截断超出局部。若s1和s2指向的内存空间重叠,则作未定义解决。返回值:返回s1的值。char *strncat(char *s1,const char *s2,size_t n){ char *tmp = s1; while(*s1) s1++; //后退到s1的开端处 while(n--) if(!(*s1++ = *s2++)) break; //遇到'\0'就完结循环 *s1 = '\0'; //在s1的开端插入'\0' return tmp; }strcmp和strncmp函数:比拟字符串的大小关系char *strcmp(char *s1,const char *s2)头文件:#include<string.h>阐明:比拟s1指向的字符串和s2指向的字符串的大小关系。返回值:若s1和s2相等,则返回0;若s1大于s2,则返回正整数值,反之返回负整数值。int *strcmp(char *s1,const char *s2){ while(*s1 == *s2){ if(*s1 == '\0') return 0; s1++; s2++; } return (unsigned char)*s1 - (unsigned char)*s2;}char *strncat(char *s1,const char *s2,size_t n);头文件:#include<string.h>阐明:比拟s1指向的字符的数组和s2指向的字符的数组的前n个字符的大小关系。返回值:若s1和s2相等,则返回0;若s1大于s2,则返回正整数值,反之返回负整数值。int *strncmp(char *s1,const char *s2,size_t n){ while(n && *s1 && *s2){ if(*s1 != *s2) return (unsigned char)*s1 - (unsigned char)*s2; s1++; s2++; n--; } if(!n) return 0; //相等 if(*s1) return 1; //s1 > s2 return -1; //s1 < s2}atoi、atol和atof函数:转换字符串int atoi(const char *nptr)头文件:#include<stdlib.h>阐明:将nptr指向的字符串转换为int型示意返回值:返回转换后的值。后果值不能用int型示意时的解决未定义。long atol(const char *nptr)头文件:#include<stdlib.h>阐明:将nptr指向的字符串转换为long型示意返回值:返回转换后的值。后果值不能用long型示意时的解决未定义。double atof(const char *nptr)头文件:#include<stdlib.h>阐明:将nptr指向的字符串转换为double型示意返回值:返回转换后的值。后果值不能用double型示意时的解决未定义。

August 19, 2020 · 1 min · jiezi

关于c++:C语言中的字符串处理库函数介绍与实现

strlen函数:求字符串的长度size_t strlen(const char *s)头文件:#include<string.h>阐明:求出s指向的字符串的长度(不包含null字符)。返回值:返回s指向的字符串的长度。size_t strlen(const char *s){ size_t len = 0; while(*s++) len++; return len;}strcpy和strncpy函数:复制字符串char strcpy(char s1,const char *s2)头文件:#include<string.h>阐明:将s2指向的字符串复制到s1指向的数组中。若s1和s2指向的内存空间重叠,则作未定义解决。返回值:返回s1的值。char *strcpy(char *s1,const char *s2){ char *tmp = s1; while(*s1++ = *s2++) ; return tmp;}char strncpy(char s1,const char *s2,size_t n);头文件:#include<string.h>阐明:将s2指向的字符串复制到s1指向的数组中。若s2的长度大于等于n,则复制到第n个字符为止。否则用null字符填充残余局部。若s1和s2指向的内存空间重叠,则作未定义解决。返回值:返回s1的值。char *strncpy(char *s1,const char *s2,size_t n){ char *tmp = s1; while(n){ if(!(*s1++ = *s2++)) break; //遇到'\0'就完结循环 n--; } while(n--) *s1++ = '\0'; //用'\0'填充残余局部 return tmp; }strcat和strncat函数:连贯字符串char *strcat(char *s1,const char *s2)头文件:#include<string.h>阐明:将s2指向的字符串连贯到s1指向的开端。若s1和s2指向的内存空间重叠,则作未定义解决返回值:返回s1的值。char *strcat(char *s1,const char *s2){ char *tmp = s1; while(*s1) s1++; //后退到s1的开端处 while(*s1++ = *s2++) ; //循环复制直至遇到s2中的'\0' return tmp;}char *strncat(char *s1,const char *s2,size_t n);头文件:#include<string.h>阐明:将s2指向的字符串连贯到s1指向的数组开端。若s2的长度大于n则截断超出局部。若s1和s2指向的内存空间重叠,则作未定义解决。返回值:返回s1的值。char *strncat(char *s1,const char *s2,size_t n){ char *tmp = s1; while(*s1) s1++; //后退到s1的开端处 while(n--) if(!(*s1++ = *s2++)) break; //遇到'\0'就完结循环 *s1 = '\0'; //在s1的开端插入'\0' return tmp; }strcmp和strncmp函数:比拟字符串的大小关系char *strcmp(char *s1,const char *s2)头文件:#include<string.h>阐明:比拟s1指向的字符串和s2指向的字符串的大小关系。返回值:若s1和s2相等,则返回0;若s1大于s2,则返回正整数值,反之返回负整数值。int *strcmp(char *s1,const char *s2){ while(*s1 == *s2){ if(*s1 == '\0') return 0; s1++; s2++; } return (unsigned char)*s1 - (unsigned char)*s2;}char *strncat(char *s1,const char *s2,size_t n);头文件:#include<string.h>阐明:比拟s1指向的字符的数组和s2指向的字符的数组的前n个字符的大小关系。返回值:若s1和s2相等,则返回0;若s1大于s2,则返回正整数值,反之返回负整数值。int *strncmp(char *s1,const char *s2,size_t n){ while(n && *s1 && *s2){ if(*s1 != *s2) return (unsigned char)*s1 - (unsigned char)*s2; s1++; s2++; n--; } if(!n) return 0; //相等 if(*s1) return 1; //s1 > s2 return -1; //s1 < s2}atoi、atol和atof函数:转换字符串int atoi(const char *nptr)头文件:#include<stdlib.h>阐明:将nptr指向的字符串转换为int型示意返回值:返回转换后的值。后果值不能用int型示意时的解决未定义。long atol(const char *nptr)头文件:#include<stdlib.h>阐明:将nptr指向的字符串转换为long型示意返回值:返回转换后的值。后果值不能用long型示意时的解决未定义。double atof(const char *nptr)头文件:#include<stdlib.h>阐明:将nptr指向的字符串转换为double型示意返回值:返回转换后的值。后果值不能用double型示意时的解决未定义。

August 19, 2020 · 1 min · jiezi

关于c++:C-指针函数和函数指针

C++ 指针函数和函数指针

August 18, 2020 · 1 min · jiezi

关于c++:C-指针函数和函数指针

C++ 指针函数和函数指针

August 18, 2020 · 1 min · jiezi

关于c++:被怀疑不是本人使用C-之父-Bjarne-Stroustrup-的-reddit-账号被冻结

C++ 之父 Bjarne Stroustrup 的 reddit 账号被解冻了?C++ 开发者 Bryce 在其 Twitter 发文称 Bjarne Stroustrup 的 reddit 账号被误判为非自己应用而解冻了。 Bryce 称,因 reddit 不置信 Bjarne Stroustrup 的账号是其自己应用的账号,而且解冻账号的操作不是零碎主动执行的,应该是其管理员手动操作。 据 Bryce 所说,账号被解冻时,Bjarne Stroustrup 的主页只能显示“This account has been suspended”。 目前,Bjarne Stroustrup 的主页曾经复原了拜访。据理解 Bryce 发推文曝光此事是因为被解冻的账号无奈申述,为寻求 reddit 工作人员帮忙,心愿相干人员看到推文后能帮忙解决问题,复原页面拜访。

August 17, 2020 · 1 min · jiezi

关于c++:被怀疑不是本人使用C-之父-Bjarne-Stroustrup-的-reddit-账号被冻结

C++ 之父 Bjarne Stroustrup 的 reddit 账号被解冻了?C++ 开发者 Bryce 在其 Twitter 发文称 Bjarne Stroustrup 的 reddit 账号被误判为非自己应用而解冻了。 Bryce 称,因 reddit 不置信 Bjarne Stroustrup 的账号是其自己应用的账号,而且解冻账号的操作不是零碎主动执行的,应该是其管理员手动操作。 据 Bryce 所说,账号被解冻时,Bjarne Stroustrup 的主页只能显示“This account has been suspended”。 目前,Bjarne Stroustrup 的主页曾经复原了拜访。据理解 Bryce 发推文曝光此事是因为被解冻的账号无奈申述,为寻求 reddit 工作人员帮忙,心愿相干人员看到推文后能帮忙解决问题,复原页面拜访。

August 17, 2020 · 1 min · jiezi

关于c++:C-Primer读书笔记第一章-开始

本系列文章为作者浏览《C++ primer》后总结的重要知识点,对简略的根底语法和常识进行了删去,总结出容易忘记和较为细节的知识点,适宜有肯定C语言语法根底的同志浏览。这本书切实是太厚了,然而又像是一个宝库,心愿我精简后的知识点能够为以前浏览过该书的同志的温习带来便当,为从未浏览过该书的同志做一个浏览的疏导。 1.2 初识输入输出iostream库蕴含两个根底类型:istream和ostream,示意输出流和输入流。 一个流就是一个字符序列,是从IO设施读入或写入IO设施的。 “流”:随着工夫的推移,字符是程序生成或耗费的。 规范库定义了4个IO对象。 1.cin:istream类型的对象,规范输出。 2.cout:ostream类型的对象,规范输入。 3.cerr:ostream类型的对象,规范谬误。用来输入正告和错误信息。 4.clog:输入程序运行时的一般性信息。 #include <iostream> :通知编译器咱们想要应用iostream库。尖括号中的名字指出了一个头文件。每个应用规范库设施的程序都必须蕴含相干头文件。#include指令和文件的名字必须写在同一行中。通常状况下,#include指令必须呈现在所有函数之外。 std::cout<<"Enter two numbers:"; :给用户打印一条音讯。这个音讯是一个字符串字面值常量。 std::cout<<endl; :endl是一个被称为操纵符的非凡值。成果是完结以后行,并将于设施关联的缓冲区中的内容刷到设施中。缓冲刷新操作能够保障目前为止程序产生的所有输入都真正写入输入流中,而不是仅仅停留在内存中期待写入流。 前缀std::指出名字cout和endl是定义在名为std的命名空间中的。命名空间能够帮咱们防止不经意的名字定义抵触,以及应用库中雷同名字导致的抵触。规范库定义的所有名字都在命名空间std中。 1.3 正文简介正文界定符不能嵌套。(/**/) 1.4 控制流当应用一个istream对象作为条件,其成果是检测流的状态。若流无效,即流未遇到谬误,则检测胜利。遇到文件结束符或一个有效输出(如读入的值不是一个整数)。istream对象的状态会变为有效。处于该状态的istream对象会使条件变为假。 在Windows零碎中,敲Ctrl+z,而后按Enter键。在Unix零碎中,包含Mac OS X零碎中没用Ctrl+d。 编译器的一部分工作是寻找程序文本中的谬误。编译器没有能力查看一个程序是否依照作者用意工作,然而能够查看模式上的谬误。如:1.语法错误(syntax error)如endl后应用了冒号而不是分号,字符串常量两侧漏掉了引号,return语句漏掉了分号等。2.类型谬误(type error)如像一个冀望参数为int的函数传递了一个字符串字面值常量。3.申明谬误(declaration error)对来自规范库的名字遗记应用std::、标识符名字拼写错误等。 当你抉择一种格局格调时,思考它会对程序的可读性和易了解性有什么影响,而一旦抉择了一种格调,就要保持应用。 1.5 类简介C++最后的一个设计焦点就是能定义应用上像内置类型一样天然的类类型。(class type) 习惯上,头文件依据其中定义的类的名字来命名。通常用.h作为头文件的后缀。规范库头文件通常不带后缀。编译器个别不关怀头文件名的格局,但有的IDE对此有特定要求。 蕴含来自规范库头文件时,应该用<>突围头文件名。对于不属于规范库的头文件,则用""突围。 从键盘重复敲入记录作为输出,十分乏味。大多数OS反对文件重定向,这种机制容许咱们将规范IO与命名文件关联起来: $ addItems <infile >outfile 假设$是IO提示符,咱们的程序曾经编译为addItems.exe的可执行文件(在UNIX中是addItems),则上述命令会从一个名为infile的文件读取记录,并将后果写入到outfile中,两个文件都位于当前目录。

August 15, 2020 · 1 min · jiezi

关于c++:C-指针和引用

援用和指针的区别和分割1. 援用只能在定义时初始化一次,之后不能扭转指向其它变量(从一而终);指针变量的值可变。 2. 援用必须指向无效的变量,指针能够为空。 3. sizeof指针对象和援用对象的意义不一样。sizeof援用失去的是所指向的变量的大小,而sizeof指针是对象地址的大小。 4. 指针和援用自增(++)自减(--)意义不一样。 5. 相对而言,援用比指针更平安。 ★不同点: 1. 指针是一个实体,而援用仅是个别名; 援用应用时无需解援用(*),指针须要解援用;援用只能在定义时被初始化一次,之后不可变;指针可变;援用没有 const,指针有 const;const润饰的指针不可变;援用不能为空,指针能够为空;“sizeof 援用”失去的是所指向的变量(对象)的大小,而“sizeof 指针”失去的是指针自身(所指向的变量或对象的地址)的大小;7. 指针和援用的自增(++)运算意义不一样; 8.从内存调配上看:程序为指针变量分配内存区域,而援用不须要分配内存区域。 ★相同点:两者都是地址的概念,指针指向一块儿内存,其内容为所指内存的地址;援用是某块儿内存的别名。 函数参数传递中值传递、地址传递、援用传递有什么区别?(1) 值传递,会为形参重新分配内存空间,将实参的值拷贝给形参,形参的值不会影响实参的值,函数调用完结后形参被开释; (2) 援用传递,不会为形参重新分配内存空间,形参只是实参的别名,形参的扭转会影响实参的值,函数调用完结后形参不会被开释; (3) 地址传递,形参为指针变量,将实参的地址传递给函数,能够在函数中扭转实参的值,调用时为形参指针变量分配内存,完结时开释指针变量。

August 15, 2020 · 1 min · jiezi

关于c++:C-指针和引用

援用和指针的区别和分割1. 援用只能在定义时初始化一次,之后不能扭转指向其它变量(从一而终);指针变量的值可变。 2. 援用必须指向无效的变量,指针能够为空。 3. sizeof指针对象和援用对象的意义不一样。sizeof援用失去的是所指向的变量的大小,而sizeof指针是对象地址的大小。 4. 指针和援用自增(++)自减(--)意义不一样。 5. 相对而言,援用比指针更平安。 ★不同点: 1. 指针是一个实体,而援用仅是个别名; 援用应用时无需解援用(*),指针须要解援用;援用只能在定义时被初始化一次,之后不可变;指针可变;援用没有 const,指针有 const;const润饰的指针不可变;援用不能为空,指针能够为空;“sizeof 援用”失去的是所指向的变量(对象)的大小,而“sizeof 指针”失去的是指针自身(所指向的变量或对象的地址)的大小;7. 指针和援用的自增(++)运算意义不一样; 8.从内存调配上看:程序为指针变量分配内存区域,而援用不须要分配内存区域。 ★相同点:两者都是地址的概念,指针指向一块儿内存,其内容为所指内存的地址;援用是某块儿内存的别名。 函数参数传递中值传递、地址传递、援用传递有什么区别?(1) 值传递,会为形参重新分配内存空间,将实参的值拷贝给形参,形参的值不会影响实参的值,函数调用完结后形参被开释; (2) 援用传递,不会为形参重新分配内存空间,形参只是实参的别名,形参的扭转会影响实参的值,函数调用完结后形参不会被开释; (3) 地址传递,形参为指针变量,将实参的地址传递给函数,能够在函数中扭转实参的值,调用时为形参指针变量分配内存,完结时开释指针变量。

August 15, 2020 · 1 min · jiezi

关于c++:C-多线程-Thread

多线程API阐明:http://www.cplusplus.com/refe... 两种类型的多任务处理:基于过程和基于线程。 基于过程的多任务处理是程序的并发执行。基于线程的多任务处理是同一程序的片段的并发执行。<thread>std::thread 在 #include<thread> 头文件中申明,因而应用 std::thread 时须要蕴含 #include<thread> 头文件。 蕴含std::thread类以及std::this_thread命名空间。治理线程的函数和类在 中申明.< atomic > :蕴含std::atomic和std::atomic_flag类,以及一套C格调的原子类型和与C兼容的原子操作的函数。 构造函数默认构造函数thread() _NOEXCEPT { // construct with no thread _Thr_set_null(_Thr); } 创立一个空的 thread 执行对象。初始化构造函数template<class Fn, class... Args>explicit thread(Fn&& fn, Args&&... args); 创立std::thread执行对象,该thread对象可被joinable,新产生的线程会调用threadFun函数,该函数的参数由 args 给出拷贝构造函数thread(const thread&) = delete;拷贝构造函数(被禁用),意味着 thread 不可被拷贝结构。Move构造函数thread(thread&& x)noexceptmove 构造函数,调用胜利之后 x 不代表任何 thread 执行对象。留神:可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached。成员函数get_id()get_id-API阐明:获取线程ID,返回类型std::thread::id对象。 inline thread::id thread::get_id() const _NOEXCEPT { // return id for this thread return (_Thr_val(_Thr)); }Returns the thread id.返回以后调用的线程ID。If the thread object is joinable, the function returns a value that uniquely identifies the thread.If the thread object is not joinable, the function returns a default - constructed object of member type thread::id.joinablejoinable-API阐明:判断线程是否能够退出期待 ...

August 14, 2020 · 2 min · jiezi

关于c++:C-多线程-Thread

多线程API阐明:http://www.cplusplus.com/refe... 两种类型的多任务处理:基于过程和基于线程。 基于过程的多任务处理是程序的并发执行。基于线程的多任务处理是同一程序的片段的并发执行。<thread>std::thread 在 #include<thread> 头文件中申明,因而应用 std::thread 时须要蕴含 #include<thread> 头文件。 蕴含std::thread类以及std::this_thread命名空间。治理线程的函数和类在 中申明.< atomic > :蕴含std::atomic和std::atomic_flag类,以及一套C格调的原子类型和与C兼容的原子操作的函数。 构造函数默认构造函数thread() _NOEXCEPT { // construct with no thread _Thr_set_null(_Thr); } 创立一个空的 thread 执行对象。初始化构造函数template<class Fn, class... Args>explicit thread(Fn&& fn, Args&&... args); 创立std::thread执行对象,该thread对象可被joinable,新产生的线程会调用threadFun函数,该函数的参数由 args 给出拷贝构造函数thread(const thread&) = delete;拷贝构造函数(被禁用),意味着 thread 不可被拷贝结构。Move构造函数thread(thread&& x)noexceptmove 构造函数,调用胜利之后 x 不代表任何 thread 执行对象。留神:可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached。成员函数get_id()get_id-API阐明:获取线程ID,返回类型std::thread::id对象。 inline thread::id thread::get_id() const _NOEXCEPT { // return id for this thread return (_Thr_val(_Thr)); }Returns the thread id.返回以后调用的线程ID。If the thread object is joinable, the function returns a value that uniquely identifies the thread.If the thread object is not joinable, the function returns a default - constructed object of member type thread::id.joinablejoinable-API阐明:判断线程是否能够退出期待 ...

August 14, 2020 · 2 min · jiezi

关于c++:C-多线程

。。。。。。。。。。。。。。。。。。。。

August 14, 2020 · 1 min · jiezi

关于c++:C-多线程

。。。。。。。。。。。。。。。。。。。。

August 14, 2020 · 1 min · jiezi

关于c++:C-关键字-const

const的用法详解

August 14, 2020 · 1 min · jiezi