
编程语言——C++
奇思妙物
专业共享软件系统服务商
展开
-
头文件与源文件
c++编程中主要包括头文件(.h后缀)和源文件(.cpp后缀)两类文件。这是一种变成风格,将声明和实现分别写在头文件和源文件中。区分头文件与源文件不同之处首先要理解编译器的工作原理:预处理:处理预编译语句,进行替换。编译:按文件编译,生成目标文件,先将高级代码编译成汇编代码,再将汇编代码编译成目标机器的机器语言。链接:将目标文件链接起来,生成可执行文件。 首先编译器会去...原创 2018-09-17 11:08:58 · 4783 阅读 · 0 评论 -
const关键字
const是一个修饰关键字,可以修饰变量,函数参数,返回值,甚至函数定义体。const是恒定不变的意思。1、对于函数参数,const只能用于修饰传入参数。输入参数如果采用值传递,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const修饰。对于自定义类型,由于产生临时对象的构造,复制,析构比较消耗时间,一般选择使用引用传递。对于内部数据类型,值传递与引用传递效率几乎...原创 2018-04-28 16:17:29 · 118 阅读 · 0 评论 -
C++11新特性
一、类型与变量相关1、nullptr:取代了NULL,专用与空指针。2、constexpr,暂不care3、using取代typedef:typdef double db //c99using db = double //c11typedef void* (*func)(int ,int); //c99using func = void* (int,int); //c114、字符串和数值类型的转换...原创 2018-04-28 15:16:54 · 129 阅读 · 0 评论 -
C++运算符
运算符分为5种类型:算术运算符,赋值运算符,关系运算符,逻辑运算符,位运算符。1、算术运算符:+ 运算符,执行加法运算,是二元运算符- 运算符,执行减法运算,是二元运算符* 运算符,执行乘法运算,是二元运算符/ 运算符,执行除法运算,是二元运算符%运算符,执行求模运算,是二元运算符*,-,+,/,%,运算优先级,遵循代数优先级,先乘除后加减当一个操作数位于两个运算符中间,运算符优先级相同时,就需要...原创 2018-05-07 00:13:05 · 505 阅读 · 0 评论 -
数组与指针
数组名一般是首元素的地址。那么后续的下标就是偏移量,这也就是为什么首元素的下标为0的原因。数组名可以当做是指向该数组第一个元素的指针。将数组作为形参传入函数,两种方式void func(int a[]) 值传递方式void func(int* a) 引用传递方式...原创 2018-05-13 14:13:44 · 138 阅读 · 0 评论 -
递归算法与递归函数
递归算法就是通过将问题不断分解为同类子问题而解决问题的方法。绝大多数编程语言是支持函数的自调用的,也就是支持函数自身来进行递归。根据计算理论,可以证明出递归可以完全取代循环,因此在很多函数编程中习惯使用递归来实现循环。但是递归有一个问题就是需要不断的调用函数,会有较大的开销。递归的函数需要逐级的返回return。每次return只能返回一级,也就是展开一个函数栈,从当前函数回到主调函数,然后继续执...原创 2018-05-13 01:01:08 · 988 阅读 · 0 评论 -
C++的前向声明
先声明类,然后再定义类。在声明之后,定义之前,这一段时空内使用这个类,只能通过指针或者引用,目前它的状态是不完全类型状态。不完全类型只能以有限方式使用。例如:class A;class B{ private: A* m_a; (不能用 A m_a)}class A { ...}前向声明的好处:不必要的#include,会增加编译时间。混乱随意的#include可能导致循环...原创 2018-05-06 00:09:44 · 324 阅读 · 0 评论 -
C++异常处理
1、throw,通过throw关键字抛出异常,可以抛出任意类型的异常。2、try , 将可能抛出异常的函数要放在try块中执行。3、catch,与try结对出现,每一个catch子句可以接一种类型的异常,或者使用...默认接受任意类型的异常。4、关于栈展开,如果一个异常发生以后,会线性的搜索函数调用栈,去搜索异常处理者,如果异常没有在抛出它的函数中被处理,就会激活栈展开。它会逐层的一个函数实体一个...原创 2018-04-27 17:05:11 · 110 阅读 · 0 评论 -
内存溢出
内存溢出实际上就是内存越界:常见的有两种情况:调用栈溢出,缓冲区溢出1、缓冲区溢出程序为了临时存取数据的需要,一般会分配一些内存空间称为缓冲区。如果向缓冲区中写入了缓冲区内无法容纳的数据,就会造成缓冲区以外的存储单元的数据被改写,成为缓冲区溢出。2、调用栈溢出每个进程的栈空间都是有限的,一般默认是8M,可以进行调整。栈满了以后执行进栈操作就是上溢,栈空了以后执行退栈操作就是下溢。如果在函数中申请的...原创 2018-04-26 17:08:32 · 117 阅读 · 0 评论 -
C++链式操作
链式操作是利用运算符进行的连续运算,它的特点是在一条语句中出现两个或两个以上相同的操作符。C++中的链式操作一定涉及到运算符的结合律。例如,赋值操作满足有结合律。1、为实现链式操作必须不能返回void类型。2、通过返回引用的方式实现链式操作。...原创 2018-05-10 20:05:45 · 492 阅读 · 0 评论 -
kmp算法
kmp算法是一种改进了的匹配字符串的算法。暴力匹配算法就是主串模式串从主串第一个字符开始匹配,符合则继续进入下一个,匹配失败重新从主串第二个字符开始重新匹配。这种方式会丢弃前面匹配得到的信息。极大降低了匹配效率。kmp的优化主要在于一次匹配失败之后,模式串的移动,尽量的右移和主串进行匹配。...原创 2018-04-26 11:13:41 · 105 阅读 · 0 评论 -
Linux系统下进程内存空间模型
参考链接:https://blog.youkuaiyun.com/gfgdsg/article/details/42709943Linux下使用虚拟内存空间给每一个进程,32位操作系统下,每个进程都有独立的4G虚拟内存空间。其中包括:1、内核区:用户代码不可见的区域,页表就存放在这个区域中。2、用户区: a、代码段:只可读,不可写,程序代码段。 b、数据段:保存全局变量,静态变量的区域。 c...原创 2018-04-25 16:35:37 · 4395 阅读 · 0 评论 -
struct和class
它们之间唯一的区别:默认访问权限:struct中的成员默认都是使用public访问修饰符。class中的成员默认都是使用private访问修饰符。默认继承权限:struct继承默认按照public继承处理。class继承默认按照private继承处理。c语言中没有classc++中两者都有。...原创 2018-04-28 16:40:59 · 135 阅读 · 0 评论 -
构造函数的初始化列表
构造函数初始化列表以一个冒号开始,接着以逗号分隔的数据成员列表。如:struct RpcClientOptions { int work_thread_num; int callback_thread_num; RpcClientOptions(): work_thread_num(4) , callback_thread_num(4) {}}初始化列表与在构造...原创 2018-04-28 17:16:24 · 1076 阅读 · 0 评论 -
C++对象中的静态成员函数和静态成员变量
使用C++对象的静态成员函数注意点:1、不可访问对象的成员变量,只能访问静态成员变量。2、默认参数中没有this指针,也是这个原因,所以无法访问类中的普通成员变量。3、静态成员函数不可访问普通成员变量(函数)4、静态成员函数可以访问静态成员变量5、可通过类型直接调用6、可通过对象名直接调用...原创 2018-08-27 11:15:12 · 420 阅读 · 0 评论 -
C++编译错误汇总
1、class后面要加 ; 2、without object , 类中成员函数没有加static关键字。3、中文分号符号4、变量拼写错误(低级错误)5、vector中自定义排序函数不能使用类成员函数6、线程入口函数不能使用类成员函数7、头文件与cpp文件不对应8、redeclaration,重复声明定义。...原创 2018-08-14 15:31:44 · 473 阅读 · 0 评论 -
vecotr中使用sort进行自定义排序问题
vector可以使用sort进行排序1、vector中是基本类型是,直接进行排序操作sort(vec.begin(),vec.end());2、vector中是结构体类型,需要自定义排序逻辑comp(const struct& a, const struct& b)sort( vec.begin() , vec.end(), comp );注意点:如果com...原创 2018-08-14 14:56:16 · 1331 阅读 · 0 评论 -
并发版本控制
并发版本控制也称为乐观锁,相对而言的有悲观锁。乐观锁使用一个版本号来实现并发控制,以解决多个用户同时修改同一条数据时的冲突问题。版本号的选择:1、自己控制,独立一套版本号,那么可以每次有更新时,版本号自增1,然后进行下发,但是这种方式不适合存在多方进行版本控制且相互之间信息不互通的情况下。2、时间戳,时间戳本身可以保持自增特性,那么就不需要多方进行信息互通,就能保证它的单向递增,每...原创 2018-08-06 22:28:03 · 709 阅读 · 0 评论 -
C字符串函数printf,sprintf,snprintf函数详解
sprintf可以将各种类型的数据构造成字符串。sprintf是个变参函数,printf和sprintf都使用格式化字符串来指定串的格式,在格式串中使用“%”开头的格式说明符,在后面的变参列表中就提供相应的变量,int sprintf(char* buffer, const char* format [,argument ]...);常见用途:1、格式化数字字符串2、控制浮...原创 2018-08-14 10:35:13 · 764 阅读 · 0 评论 -
sizeof计算类大小
占位符原创 2018-05-21 17:52:51 · 259 阅读 · 0 评论 -
STL——迭代器
迭代器:头文件<iterator>提供一种方法顺序访问一个聚合对象中各个元素。能够让容器和算法不干扰的相互发展,最后又能黏合起来。每种容器都有自己的迭代器类型。按照STL中的分类,iterator包括:1、输入迭代器,input iterator:可以被复制构造和赋值,可以自增,可以做相等性和不相等性的比较,可做右值引用。2、输出迭代器,output iterator:包括输入迭代器的...原创 2018-05-08 14:58:15 · 619 阅读 · 0 评论 -
C常用标准库及函数
常用头文件:stdio.hstdlib.hctype.hstring.hmath.hsystem.h1、stdio库:主要功能是输入输出操作,包括文件输入输出,标准输入输出。输出函数: int puts(const char* str) 把一个字符串写出到标准输出int printf(char *format,args,…) 把args,…的值以format指定的格式输出到标准输出设备,输出字符...原创 2018-05-08 12:21:42 · 10747 阅读 · 0 评论 -
C++字符串操作函数
针对C语言类型的字符串操作:<string.h>C++中<cstring>size_t strlen(const char* s) 计算字符串的长度,不包括 \0 的长度。int strcmp(const char*,const char*) 比较两个字符串,若str1 == str2 , 返回零若str1 > str2 ,返回正数若str1 < str2,返...原创 2018-05-07 17:55:55 · 240 阅读 · 0 评论 -
C++ 单引号和双引号区别
单引号是字符型双引号是字符串型单引号引起的一个字符实际上代表一个整数。双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针。该数组会被双引号之间的字符以及一个额外的二进制为零的字符 '\0' 初始化。#include <stdio.h>void test(char c) { printf("Got character %c\n", c);}void test(const cha...原创 2018-05-07 16:23:16 · 21595 阅读 · 0 评论 -
函数对象/仿函数
函数对象也被称为智能型函数。在类中重载了()函数调用运算符,那么该类的对象就可以像使用普通函数一样进行调用,该对象就被称为函数对象。函数对象与普通函数的优势在于:1、函数对象可以有自己的状态,我们可以在类中定义状态变量,这样一个函数对象在多次的调用中可以共享这个状态。2、函数对象有自己特有的类型,可以传递相应的类型作为参数来实例化相应的模板。函数对象使用例子:1、set容器中自定义类型的比较排序函...原创 2018-05-07 12:19:59 · 250 阅读 · 0 评论 -
const指针
const与指针的结合:const char * p / 指向整形常量的指针,它指向的值不能修改。char * const p / 指向整形的常量指针,它不能再指向别的变量,但是它指向的值可以变。...原创 2018-05-03 15:28:22 · 85 阅读 · 0 评论 -
C++内存操作函数
void* memcpy(void* dest , void* src, size_t length)函数:函数从src的起始位置复制length个字节到dest的内存起始位置,它并不关心数据类型,只是逐字节的进行复制。注意点:1、dest指针要分配足够的空间,大于或等于 length个字节的空间。如果没有分配空间,会出现断错误。2、dest和src所指的内存空间不能重叠。即dest < s...原创 2018-05-03 15:19:04 · 1519 阅读 · 0 评论 -
虚函数
虚函数:动态多台的一种机制。虚函数使用注意点:虚函数只能用于修饰类的普通成员函数,不可以是全局函数,否则会编译出错。静态成员函数不能是虚函数,静态函数是属于 类的,不属于任何一个对象,会编译出错。构造函数不能是虚函数,构造时就会进行相关的资源申请,虚函数是通过虚函数表实现的,虚函数表也需要在构造时初始化,所以构造函数不能是虚函数。构造函数也不需要是虚函数,因为我们在构造一个对象时,都会明确需要构造...原创 2018-04-04 12:18:32 · 252 阅读 · 0 评论 -
类与对象
类:我们声明定义一个类。对象:类的一个实例。类中的成员函数,隶属于所有类的对象,在编译时,成员函数的地址已经确定。类中的成员变量,隶属于每一个具体的对象,需要在对象构造时初始化,以及析构时进行清理,成员函数访问对象中的成员变量时都是通过this指针。 1 class A 2 { 3 public: 4 void foo() 5 { 6 cout<&l...原创 2018-04-04 11:33:13 · 115 阅读 · 0 评论 -
STL:map与multimap
关联容器map:映射multimap:多重映射底层存储结构:红黑树(自平衡的二叉查找树)所以map内部数据都是有序的。默认是通过key值进行排序。默认遍历方式是中序遍历。map的构造和初始化:map<int,string> mapStudent;map的数据插入:1、insert插入:mapStudent.insert(pair<int,string>(1,"zhangle...原创 2018-04-04 01:11:01 · 175 阅读 · 0 评论 -
new与malloc区别
两者都用于初始化分配内存。malloc:引入头文件 stdlib.h内存大小:malloc通过计算得到一块新内存。内存分配过程:使用malloc,向操作系统申请内存,操作系统会遍历空间内存节点,将第一个大于申请空间的内存分配给程序,然后将空闲链表节点删除。成功分配:返回值为指向被分配内存的指针。失败分配:返回NULL。返回类型:void* 可通过强制转换为其他任意类型。释放:free,使用free...原创 2018-04-04 00:30:01 · 197 阅读 · 0 评论 -
C++类型转换
C语言中对内置类型可以进行强制转换,但是这种转换是不安全的。所以一般,目前我们推荐使用C++中的cast函数进行类型转换。基本数据类型之间的转换类型的层次转换static_cast (编译类型检查)1、基本数据类型之间的转换。如int转char,int转enum等。使用中的转换安全性需要开发者自己去保证。如int转换为char。那么static_cast只是纯粹的截断,把int的低8位的内容复制到...原创 2018-04-16 17:51:19 · 110 阅读 · 0 评论 -
STL:Vector向量
头文件: <vector>存储方式:顺序容器,类似数组,开辟整块内存进行顺序存储。在虚拟内存空间是整块的。内存管理:vector会有内存迁移能力,当当前内存不够用时,就会重新开辟一块大内存将数组整体复制过去,再释放以前的内存,这样效率会很低。当发生内存重新分配以后,以前所有迭代器对象会全部失效。看个图:常用方法:reserver():预留一定的空间,改变capcaity,不改变size...原创 2018-04-03 15:02:36 · 170 阅读 · 0 评论 -
工厂模式——C++
工厂模式是创建型模式,利用工厂来生产类实例。主要解决:接口选择的问题。何时使用:明确计划不同条件下创建不同实例。适用场景:作为一种创建型模式,在任何需要生成复杂对象的地方,都可以使用工厂模式。复杂对象适合使用工厂模式,简单对象,特别是只需要一个new就可以完成创建的对象,无需使用工厂模式。引入工厂类会增加系统的难度。工厂方法返回基类指针,创建的对象一般是该基类的派生类,通过虚函数机制,实现多态。工...原创 2018-04-10 12:11:32 · 141 阅读 · 0 评论 -
C++构造函数
构造函数使用相关注意点:构造函数是没有返回值,在方法中也不能有return。构造函数中不能抛异常,如果在构造函数中抛异常,会导致对象半构造,而对象没有完全构造完成,是不会调用析构函数的,这时就会出现资源泄露。构造函数的初始化列表比在构造函数中进行赋值初始化要高效。构造二步法,一般不建议在构造函数中有过于复杂的构造,如一定要有,可建议使用构造二步法,如再定义一个init函数进行初始化工作。拷贝构造函...原创 2018-03-31 01:22:56 · 173 阅读 · 0 评论 -
Boost——无锁队列queue
boost提供了三种无锁方案:boost::lockfree::queue;支持多生产者,多消费者的无锁队列;boost::lockfree::stack;支持多生产者,多消费的无锁栈;boost::lockfree::spsc_queue;支持单生产者,单消费者的无锁队列,比第一个效率更高。实际上,都是通过轻量级原子锁实现的lock free,并不是真正意义上的无锁。...原创 2018-03-30 18:00:51 · 3844 阅读 · 0 评论 -
预处理命令
一个可执行的C++二进制的整个构建过程包括:预处理,编译,汇编,链接。在预处理阶段,就是预处理器对预处理命令进行处理,常用的预处理命令主要包括三类:1、宏定义,2、文件包含,3、条件编译。宏定义,#define ;实际上在effective C++中,并不太建议使用define,建议尽量使用const,inline,enum替换#define,原因在于define的常量在编译器处理之前已经完成替...原创 2018-03-29 23:16:19 · 538 阅读 · 0 评论 -
智能指针——C++
产生原因:C++没有自动内存回收机制。平常我们在使用C++开发过程中,动态申请内存,使用new或malloc,然后通过指针去使用;那么,使用结束以后,必须要显式的调用delete或free操作,释放对应的动态存储空间,不然就会产生内存泄露的问题。这整个操作是需要程序员去进行,程序员的不小心就 很容易造成内存泄露的问题。而且内存泄露问题一般隐藏比较深,难以发现,也难以定位。基于以上原因,有了智能指针...原创 2018-03-29 11:09:46 · 166 阅读 · 0 评论 -
观察者模式——C++
一个通知者,多个观察者。通知者主要方法:1、注册观察者:在vector中push back一个观察者。2、通知观察者:遍历vector中的观察者,并调用观察者的notify方法。观察者主要方法:1、通知方法:将observer中的原子变量进行变更。通知者类中定义一个成员变量notifier,观察者类中定义一个成员变量observer,通知者方法中,在需要进行通知的地方调用 notifyall 方法...原创 2018-03-28 23:39:27 · 125 阅读 · 0 评论 -
内存分配系统调用:brk和mmap
参考链接:https://blog.youkuaiyun.com/getnextwindow/article/details/295567551、brk是将进程堆的最高地址指针往高地址推。2、mmap是在进程的虚拟地址空间中文件映射区域(堆与栈中间)找一块空闲的虚拟内存,通常是动态库的映射等。这两种方式都是分配虚拟内存。在malloc中的分配释放内存也是通过brk和mmap这些系统调用实现的。malloc小于...原创 2018-04-25 15:59:45 · 1955 阅读 · 0 评论