C/C++
Vincent's Blog
A bug machine made in HUST
展开
-
右值引用
右值引用1. 什么是右值引用右值引用是C++11新加的一种引用类型,是一种仅能绑定到右值上的引用。不同于左值引用仅用一个&表示,右值引用用两个&&表示。int x{ 5 };int& lref{ x }; // l-value refrence initialized with l-value x int&& rref{ 5 } // r-value refrence initialized with r-value 5右值引用有两个非常有用的性原创 2020-10-19 15:35:13 · 3745 阅读 · 1 评论 -
智能指针和移动语义
intro to smart pointer and move semantics(翻译改写自https://www.learncpp.com/cpp-tutorial/15-1-intro-to-smart-pointers-move-semantics/)1. 裸指针导致的内存泄漏问题考虑下面这个函数,在这个函数中我们动态申请了一片内存。void someFunction(){ Resource *ptr = new Resource; // Resource is a struct原创 2020-10-19 11:03:34 · 712 阅读 · 0 评论 -
VS静态链接和动态链接
最近接手了一个新的项目, 遇到一系列链接错误,折腾的头大。上周末终于完全解决了各个project之间的依赖及链接问题, 趁此机会,我仔细阅读了一些资料并在vs2019上做了一些实验,算是基本搞清楚了静态链接和动态链接的一些基本概念, 在这里记录一下,希望对自己也对其他人有所帮助。下面通过一个实验来解释在vs2019环境下如何进行静态链接和动态链接。1. 新建三个工程首先我们需要新建一个名为Test的解决方案,并在Test中新建两个工程,Printer和Calc, Configuration均配置为De原创 2020-09-13 22:08:47 · 3036 阅读 · 4 评论 -
【C】C语言输入输出缓冲区
1.一个“诡异”的程序先来看一个小程序,分析一下运行结果#include<stdio.h>int main(){ printf("hello"); int i = 0; for(;i<10;i++) { putchar('.'); sleep(1); }原创 2016-06-19 18:57:33 · 13594 阅读 · 10 评论 -
【Linux/C】如何编译和使用库文件
1. 库文件分类库文件可以分为两类,静态库和动态库。 链接静态库的程序特点:1. 程序较大;2.不容易升级;3.容易部署 链接动态库的程序特点:1. 程序较小;2.容易升级;3.不容易部署2. 存档文件(静态库)存档文件(Archive),也就是静态库,就是一系列目标文件的集合(大致相当于windows下的*.LIB文件)。当你提供一个存档文件给链接器的时候,链接器会在存档文件中寻找所需原创 2016-06-21 20:55:50 · 5777 阅读 · 0 评论 -
【Linux/C】程序的编译和链接--例子
上一篇文章已经讲过了程序从源文件到可执行文件之间的实现过程,这篇文章讲一个简单的例子。 首先准备三个文件。//main.c文件内容#include<stdio.h>#include "fun.h"int main(){ printf("the answer is %d\n",calc(5,6)); printf("hello,world.\n"); return 0原创 2016-06-23 16:44:53 · 947 阅读 · 0 评论 -
C程序的编译链接过程
程序由源文件编译得到可执行文件看起来好像是很简单的过程,windows的IDE环境下,点一下bulid就可以生成可执行文件,在Linux环境下,gcc编译器也提供了很多选项可以很方便的从源文件生成可执行文件。但是实际上程序的编译和链接是一个比较复杂的过程。大致可以分为四步:1.预处理;2.编译;3.汇编;4.链接。我们以最经典的hello,world程序来下面来分析一下各个步骤的作用分别是什么。//原创 2017-04-17 17:21:55 · 1394 阅读 · 1 评论 -
判断IP是否在IP段内
项目当中衍生出来的一道题,给定一个IP段以及一个IP,判断这个IP是否在此IP段内。IP段的表示方法有两种,一种如192.168.1.0/24,另一种如192.168.1.1-254 例:1.input: 192.168.1.0/24 192.168.1.56output: true//192.168.1.0/24表示的IP范围是192.168.1.1~192.1...原创 2018-09-09 15:56:58 · 3500 阅读 · 0 评论 -
qt记事本(精简版)
昨天在家闲的无聊,折腾了一下qt,发现qt的信号与槽机制真的蛮好,简单好用,省了很多事情,于是用qt模仿windows 记事本实现了一个精简版的记事本,感觉效果还不错。1. 功能点列表写代码之前之前首先明确需要要实现的功能,我打算实现的功能点如下: 1. 页面布局 1. 标题栏显示打开的文件名称(包括路径),如果没有打开任何文件,或者新建文件还没有保存,显示“无标题” 2. 工具栏...原创 2018-10-22 11:16:11 · 2247 阅读 · 2 评论 -
进程通信(1)管道
进程之间通信的方式有很多种,主要包括管道命名管道信号消息队列共享内存信号量套接字其中,管道是最早的一种进程间通信机制,主要适用于具有亲缘关系之间的进程间通信,比如,父进程与子进程之间,或者同一个父进程的两个子进程之间。同时,管道是一中半双工的通信,数据只能单向流动,从一段写入,另外一段读出。下面通过几个例子来看一下管道如何使用。1. 函数原型 #include &lt;un...原创 2018-10-31 14:35:42 · 331 阅读 · 0 评论 -
查看系统头文件包含路径
cpp -v命令可以查看头文件包含路径,记录一下。linux下执行结果:Using built-in specs.COLLECT_GCC=cppTarget: x86_64-unknown-linux-gnuConfigured with: ../configure --enable-checking=release --enable-languages=c,c++ --disable-...原创 2018-11-09 10:55:59 · 2296 阅读 · 0 评论 -
关于数组初始化
1.定义一个数组,如果没有初始化,那么数组元素的值是不确定的。2.数组可以用花括弧括起来的一系列数值来初始化,数值之间用逗号分隔,数值和逗号之间可以有空格符3.初始化时,如果数值个数少于数组元素个数,那么多余的数组元素被初始化为04.初始化时,如果数值个数多余数组元素个数,编译会报错,这个问题可以在数组声明时省略方括号中的数字,让编译器自动匹配数组大小和初始化列表中的数值个数。#include<st原创 2017-03-30 17:17:20 · 2193 阅读 · 0 评论 -
map应用:反片语
map应用:反片语map就是从键(key)到值(value)的映射。因为重载了[]运算符,map像是数组的高级版。例如,我们可以用一个map例题:输入一段文本,找出所有满足条件的单词,需满足的条件是该单词不能通过字母重拍得到文本中的另外一个单词。在判断时,字母不区分大小写,但在输出时应保留输入中的大小写,按照字典序进行排列输出(所有大写字母在所有小写字母的前面) 比如一段文本中出现God和dog,原创 2016-10-01 22:40:30 · 413 阅读 · 0 评论 -
set应用:提取文本中所有不同的单词
set应用:提取文本中所有不同的单词set是一个常用的容器,是数学意义上的集合–每个元素最多只能出现一次。和sort函数一样,自定义的类型(struct、class)也可以构造set,但是同样必须定义“小于”运算符。 例题: 输入一个文本,找出所有不同的单词,按照字典序从小到大输出。单词不区分大小写,大写的单词按小写输出。这里的单词定义为连续的字母序列。 样例输入:I am a student原创 2016-10-01 20:46:29 · 1480 阅读 · 0 评论 -
【C】两个有序序列的中位数
程序代码:#include<stdio.h>#define max 100000int main(){ int i=0, n; scanf("%d",&n); int a[max]; int b[max]; for(;i<n;i++) scanf("%d",&a[i]); for(i=0;i<n;i++)原创 2016-07-16 19:12:29 · 917 阅读 · 0 评论 -
【C】最大子列和问题
程序代码:#include<stdio.h>#define MAX 100000long long maxSeq(int num[],long long n){ long long tmp=0,max=0; long long i=0; for(i=0;i<n;i++) { if(tmp < 0) tmp = num[i]原创 2016-07-17 14:32:12 · 426 阅读 · 0 评论 -
【C】程序的编译与链接--简单介绍
程序由源文件编译得到可执行文件看起来好像是很简单的过程,windows的IDE环境下,点一下bulid就可以生成可执行文件,在Linux环境下,gcc编译器也提供了很多选项可以很方便的从源文件生成可执行文件。但是实际上程序的编译和链接是一个比较复杂的过程。大致可以分为四步:1.预处理;2.编译;3.汇编;4.链接。我们以最经典的hello,world程序来下面来分析一下各个步骤的作用分别是什么。//原创 2016-06-23 16:14:13 · 499 阅读 · 0 评论 -
求一个整数的二进制表示中1的个数
求一个整数的二进制表示中1的个数求一个整数的二进制表示中1的个数有一个巧妙的方法,如下:int CountOne(int n){ int count; while(n) { n=n&(n-1); count++; } return count;}原创 2016-09-12 15:00:38 · 470 阅读 · 0 评论 -
memset函数
1.memset函数声明memset函数的声明包含在<string.h>中 其原型是: void * memset ( void * ptr, int value, size_t num ); 其作用是: 将从ptr所指的内存单元开始num个字节的值全部置为value,并返回ptr指针。 例如下面这段代码:/* memset example */#include <stdio.h>#i原创 2016-07-27 11:20:26 · 476 阅读 · 0 评论 -
【C】两个有序链表序列的合并
程序代码:#include<stdio.h>#include<stdlib.h>struct ListNode{ int data; struct ListNode* next;};typedef struct ListNode node;int main(){ int i; node l1,l2,l3; l1.next=NULL; l2原创 2016-07-16 20:48:49 · 1205 阅读 · 0 评论 -
【C】树的层序遍历
1.基本思路层序遍历的基本思路就是, 1.根节点入队列。 2.根节点出队,同时将根节点左儿子和右儿子入队 3.结点出队,同时将该节点的左儿子和右儿子入队 4.重复3直到队列为空2.算法实现void layerprint(struct TreeNode* r){ struct queue q1; //创建队列 q1.s=&q1.node[0]; //原创 2016-06-30 10:58:00 · 415 阅读 · 0 评论 -
【C】两个有序链表序列的交集
程序代码:#include<stdio.h>#include<stdlib.h>struct ListNode{ int data; struct ListNode* next;};typedef struct ListNode node;int main(){ int i; node l1,l2,l3; l1.next=NULL; l2原创 2016-07-16 20:13:13 · 8182 阅读 · 1 评论 -
C语言单元测试框架unit的使用
针对C语言的测试框架相比其他语言要少一些,本文简单介绍一下Cunit框架的基本使用方法,权当备忘吧。Cunit的组织框架如下图所示:将单个测试用例打包到一个suite中,这些suite在Registry中注册。registry中的所有suite/tests可以使用单个函数调用运行,也可以运行选定的套件或测试。下面看一个例子首先我们新建文件,写一个待测试函数,这里以一个字符串转换数字函数为例,...原创 2018-11-12 17:26:30 · 12179 阅读 · 0 评论 -
c++智能指针
0.使用普通指针带来的问题c++ 的内存管理是一个让人非常头疼的问题,当我们写一个new语句时,如果没有写响应的delete语句,就会造成内存泄漏的问题。或者就算我们写了delete语句,有可能程序还没有执行到delete语句就返回或者跳转到其他的语句,一样会造成内存泄漏。看下面这个例子void test(){ double *p = new double; *p = 5.5; ret...原创 2019-01-03 18:08:02 · 359 阅读 · 0 评论 -
记一个bug
今天,有一个同事写了下面这样一段测试代码。这段代码的功能非常简单,从头到尾打印vector中的每个元素(vector的规模较小,不会超过int的表示范围)。看起来好像没什么问题?但是跑起来却发现时不时会出现Segmentation fault错误。这是为什么呢?void printVector(vector&amp;lt;int&amp;gt; &amp;amp;s){ for (int i = 0; i &amp;...原创 2019-02-13 19:47:18 · 243 阅读 · 0 评论 -
C++两种构造方法的效率对比
0. 为什么初始化列表效率高?C++中类的构造函数写法有两种,一种是使用初始化列表,一种是在代码块中赋值。很多书中(包括C++ Primer、C++ Primer Plus等等)都会提到应该尽量使用初始化列表而不是在代码块中赋值,因为使用初始化列表通常比在代码块中赋值效率要高。但是这个结论是怎么来的?如何验证呢?今天我们来设计一个小例子对比一下两者之间的区别。1. 定义一个Man类首先,我们...原创 2019-03-10 13:24:52 · 1167 阅读 · 0 评论 -
深入理解static关键字(2)
上一篇文章当中讨论了C语言中static关键字的用法。这一篇来看一下C++中的static。C语言中的用法在C++中一样适用,但是C++中static又新增了一种用法,用来修饰类的成员,称为类的静态成员。1.static修饰类的成员类的静态成员不属于任何对象,类的实例中不包含任何与静态数据成员有关的数据。举个例子:// teacher.hclass teacher {public: ...原创 2019-03-07 20:55:27 · 356 阅读 · 0 评论 -
记一个输入缓冲bug
在论坛上看到一个同学贴的一段代码如下:#include<stdio.h>int main(){ int num, cnt, sum = 0; cnt = scanf("%d", &num); while (cnt != 1) { printf("cnt = %d\n", cnt); cnt = scanf("%d",...原创 2019-03-15 23:39:46 · 284 阅读 · 0 评论 -
从汇编的角度理解什么是引用
C++中引入的引用类型,给我们带来了很大的方便。通过向函数传递引用,我们既可以享受像传递指针一样直接修改变量值的优点,又避免了空指针和野指针造成的问题。在日常开发中我们应该尽量使用引用,避免使用指针。但是引用到底是什么,看起来好像引用跟指针有着千丝万缕的联系,同时两者又有很大的差别,那么引用跟指针到底是什么关系呢?教材上通常会说,引用就是变量的别名,但是光看这句话可能还是不太明白引用的本质。其实按...原创 2019-03-15 23:42:06 · 1289 阅读 · 0 评论 -
如何实现一个min stack
如何实现一个min stackQ: 如何设计一个特殊的栈,支持min()操作,返回栈中的最小元素.这个问题来源于去年面试遇到的一道题目,面试官给了20分钟时间让设计这样一个栈.当时时间有限,虽然写出来了一个版本,但是那个版本还存在很多的问题,比如不够通用,只能支持int类型数据;同时,效率也不高, 存在大量的数据拷贝.面试完后又仔细思考了一下,重新写了一个版本,记录一下,分享给大家!这个版本...原创 2019-05-08 13:31:43 · 754 阅读 · 0 评论 -
GDB调试技巧-打印vector的元素值
GDB调试技巧-打印vector的元素值我们平常在使用GDB调试程序的时候,往往需要查看一个STL容器里面存储的元素的值是多少。但是用GDB的p命令打印容器,我们会得到一堆乱七八糟的东。比如有一个vector<int> nums = {1,2,3},当我们使用p nums命令时,我们得到的结果是:(gdb) p nums$1 = {<std::_Vector_base<...原创 2019-05-28 00:16:22 · 10521 阅读 · 3 评论 -
如何正确删除vector中的元素
今天来探讨C++中的一个基础问题。如何正确地删除`vector`中符合条件的某元素。比如,有一个`vector<int> nums = {1, 2, 2, 2, 2, 3, 5}`,要求删除`nums`中所有值为2的元素。C++初学者可能很快就写出代码:原创 2019-06-18 23:19:37 · 36323 阅读 · 3 评论 -
线程总结3-屏障
线程总结3-屏障0. 屏障屏障是用户协调多个线程并行工作的同步机制。屏障允许所有的合作线程都到达某一点,然后从该点继续执行。1. 相关函数1.1. 初始化#include<pthread.h>int pthread_barrier_init(pthread_barrier_t *restrict barrier, const ...原创 2019-07-07 21:55:18 · 559 阅读 · 1 评论 -
如何实现一个string类(2)
上一篇文章实现了myString类的构造函数、拷贝构造函数和析构函数,并且重载了<<运算符。这篇文章来讨论一下赋值运算、下标操作和+=拼接字符串操作。1. 赋值运算符重载首先来看一下赋值运算符重载。在实际应用中,我们经常遇到需要将一个对象赋值给另外一个对象的情况,那么就需要使用赋值运算符=。跟默认的拷贝构造函数一样,如果我们没有显式地定义一个赋值运算符重载函数,那么编译器会提供一...原创 2019-03-04 11:54:04 · 495 阅读 · 0 评论 -
如何实现一个string类(1)
string类是C++当中用的非常频繁的一个类,它提供了很多处理字符串的函数,让字符串的使用变得像int、float等built-in类型一样简单。string类的实现包含了大量c++语言的知识,其中有很多值得讨论的问题。自己动手实现一个string类是学习c++语言的好方法,可以检验自己一下C++基础知识掌握的如何。下面我们来尝试动手实现一个字符串类。1.定义成员变量我们的字符串类需要处理...原创 2019-03-04 11:53:27 · 2416 阅读 · 0 评论 -
赋值运算符重载
0.对象赋值时发生了什么C语言中允许把一个结构体赋值给另外一个相同类型的结构体,C++允许把一个对象赋值给另一个同类的对象。这是通过自动为类重载赋值运算符实现的。这种赋值运算符重载函数yuan原型如下。Class_name &amp; Class_name::operator=(const Class_name &amp;);它接受一个指向对象的常引用,并返回一个指向类对象的引用。那么c+...原创 2019-01-01 02:03:33 · 563 阅读 · 0 评论 -
虚函数表分析
0.多态C++几个的抽象、封装、继承和多态几大特性当中,多态是最为重要的一个。所谓多态(这里指狭义的多态)就是父类指针或引用指向子类对象,然后可以通过父类指针或引用调用子类的成员函数。 刚开始学习多态的时候,觉得多态非常神奇,同时也非常费解。后来了解到c++的多态是通过虚函数表来实现的,但是一直也没有做一个系统的总结。今天写几个例子梳理一下c++是怎么通过虚函数表来实现多态的。1. 单继承虚函...原创 2019-01-01 14:49:52 · 513 阅读 · 0 评论 -
构造函数、析构函数和虚函数的关系
首先明确两点构造函数不可能定义为虚函数虚函数的目的是通过父类引用或者指针调用子类的成员函数。而构造函数的目的是创建对象。创建子类对象时,将调用子类的构造函数,而不是父类的构造函数。子类的构造函数将使用父类的一个构造函数。这种顺序不同于继承机制。因此,子类不继承父类的构造函数,所以将类的构造函数声明为虚函数没有意义。这个如果不能理解,记住就好了。父类的析构函数应该是虚函数关于第二点,举个...原创 2019-01-01 22:42:30 · 1863 阅读 · 0 评论 -
网络字节序和主机字节序
现代CPU的累加器一次至少能装载4字节的数据。一个int类型占据4个字节(假设在32位系统上),那么这4字节在内存中排列的顺序将影响到它被累加器装载成的整数的值。这既是字节序的问题。字节序分为大端字节序和小端字节序。假设有int a = 0x11223344大端序:整数高位字节在低地址内存,整数低位字节在高位地址。小端序:整数高位字节在高地址内存,整数低位字节在低位地址。一般来说,...原创 2019-01-11 14:18:44 · 980 阅读 · 0 评论 -
深入理解C++多态
在之前发的一篇文章《虚函数表分析-C++多态的实现》中,已经分析过C++多态的实现原理。这篇文章来看一个具体的例子,这个例子来源于一道经典的C++面试题,看起来蛮简单,但是相当多的人都在这里翻车了。这篇文章希望能把这道题阐述清楚,给大家带来一些帮助。题目给了下面这样一段代码(代码我略有更改),问程序的输出是什么,并解释输出结果。class A {public: int a; v...原创 2019-02-20 13:56:01 · 474 阅读 · 0 评论