C++
文章平均质量分 73
1390811049
这个作者很懒,什么都没留下…
展开
-
unique_ptr编译错误can‘t delete an incomplete type
如果一个类没有用户声明的构造或者析构函数,析构函数会被隐式地声明为默认析构函数(8.4)。隐式声明的析构函数是其类的内联公有成员。在编译时遇到test没有声明构造和析构就会默认生成,但是在这个位置还没有include base的头文件,展开模板就会报错。因为test类没有声明构造或者析构函数所以编译器生成了一个默认的构造和析构函数。使用了前置声明的base。原创 2023-06-19 19:14:13 · 597 阅读 · 0 评论 -
function源码
std::function源码原创 2023-03-13 23:56:32 · 316 阅读 · 1 评论 -
C++构造函数中不能使用多态
在C++构造函数中使用多态原创 2022-06-27 23:30:48 · 489 阅读 · 0 评论 -
C++11的各种锁
Mutex(互斥锁)什么是互斥量(锁)?这样比喻:单位上有一台打印机(共享数据a),你要用打印机(线程1要操作数据a),同事老王也要用打印机(线程2也要操作数据a),但是打印机同一时间只能给一个人用,此时,规定不管是谁,在用打印机之前都要向领导申请许可证(lock),用完后再向领导归还许可证(unlock),许可证总共只有一个,没有许可证的人就等着在用打印机的同事用完后才能申请许可证(阻塞,线程1lock互斥量后其他线程就无法lock,只能等线程1unlock后,其他线程才能lock)。那么,打印机就是原创 2021-08-08 16:29:43 · 3713 阅读 · 1 评论 -
基于C++11实现线程池
为何需要线程池那么为什么我们需要线程池技术呢?多线程编程用的好好的,干嘛还要引入线程池这个东西呢?引入一个新的技术肯定不是为了装酷,肯定是为了解决某个问题的,而服务端一般都是效率问题。我们可以看到多线程提高了CPU的使用率和程序的工作效率,但是如果有大量的线程,就会影响性能,因为要大量的创建与销毁,因为CPU需要在它们之间切换。线程池可以想象成一个池子,它的作用就是让每一个线程结束后,并不会销毁,而是放回到线程池中成为空闲状态,等待下一个对象来使用。C++中的线程池但是让人遗憾的是,C++并没有在语原创 2021-07-30 00:22:42 · 662 阅读 · 0 评论 -
C++ rb_tree红黑树
在 STL 编程中,容器是我们经常会用到的一种数据结构,容器分为序列式容器和关联式容器。两者的本质区别在于:序列式容器是通过元素在容器中的位置顺序存储和访问元素,而关联容器则是通过键 (key) 存储和读取元素。本篇着重剖析关联式容器相关背后的知识点,来一张思维导图容器分类前面提到了,根据元素存储方式的不同,容器可分为序列式和关联式,那具体的又有哪些分类呢,这里我画了一张图来看一下。关联式容器比序列式容器更好理解,从底层实现来分的话,可以分为 RB_tree 还是 hash_table,所有暴原创 2021-07-25 23:57:16 · 760 阅读 · 5 评论 -
STL 迭代器与 traits 编程技法
在 STL 编程中,容器和算法是独立设计的,容器里面存的是数据,而算法则是提供了对数据的操作,在算法操作数据的过程中,要用到迭代器,迭代器可以看做是容器和算法中间的桥梁。迭代器设计模式为何说迭代器的时候,还谈到了设计模式?这个迭代器和设计模式又有什么关系呢?在设计模式中,关于 iterator 的描述如下:一种能够顺序访问容器中每个元素的方法,使用该方法不能暴露容器内部的表达方式。而类型萃取技术就是为了要解决和 iterator 有关的问题的。在 C++ 语言里面,我们可用以下方式来简单区分一下原创 2021-07-24 18:26:50 · 100 阅读 · 0 评论 -
C++ 模板
C++模版的诞生程序本质是数据结构+算法,任何一门语言都可以这样理解,这个公式对计算机科学的影响程度足以类似物理学中爱因斯坦的“E=MC^2”——一个公式展示出了程序的本质。最初C++是没有标准库的,任何一门语言的发展都需要标准库的支持,为了让C++更强大,更方便使用,Bjarne Stroustrup觉得需要给C++提供一个标准库,但标准库设计需要一套统一机制来定义各种通用的容器(数据结构)和算法,并且能很好在一起配合,这就需要它们既要相对的独立,又要操作接口保持统一,而且能够很容易被别人使用(用到实原创 2021-07-22 00:16:02 · 330 阅读 · 5 评论 -
C++11多线程
线程:线程是操作系统能够进行CPU调度的最小单位,它被包含在进程之中,一个进程可包含单个或者多个线程。可以用多个线程去完成一个任务,也可以用多个进程去完成一个任务,它们的本质都相当于多个人去合伙完成一件事。多线程并发:多线程是实现并发(双核的真正并行或者单核机器的任务切换都叫并发)的一种手段,多线程并发即多个线程同时执行,一般而言,多线程并发就是把一个任务拆分为多个子任务,然后交由不同线程处理不同子任务,使得这多个子任务同时执行。C++多线程并发: (简单情况下)实现C++多线程并发程序的思路如下:将任原创 2021-07-21 23:37:10 · 433 阅读 · 0 评论 -
STL 配置器(allocator)
配置器:负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的 class template。空间配置器:整个 STL 的操作对象(所有的数值)都存放在容器之内,而容器一定需要配置空间以存放内容。什么是 allocator?allocator 有什么用?我们需要对 C++ 的 allocator 的堆内存接口调用顺序有个清晰的认识,如下图所示。allocator 堆内存管理接口 STL 的容器(eg: vector、stack、deque等)有一个共同特征,就是原创 2021-07-21 22:12:01 · 1095 阅读 · 3 评论 -
C++11随机数
在C++11之前,现有的随机数函数都存在一个问题:在利用循环多次获取随机数时,如果程序运行过快或者使用了多线程等方法,srand((unsigned)time(null))这样的设置当前系统时间为种子的方法每次返回的随机数都是一样的。而C++11中提供了真随机数做种子的方法来解决这一问题。random_device标准库提供了一个非确定性随机数生成设备.在Linux的实现中,是读取/dev/urandom设备;Windows的实现是用rand_s,使用的是操作系统来生成加密安全的伪随机数随机数生成原创 2021-07-21 00:34:44 · 1544 阅读 · 0 评论 -
C++处理日期和时间的chrono库
C++11 中提供了日期和时间相关的库 chrono,通过 chrono 库可以很方便地处理日期和时间,为程序的开发提供了便利。chrono 库主要包含三种类型的类:时间间隔duration、时钟clocks、时间点time point。时间间隔 duration常用类成员duration表示一段时间间隔,用来记录时间长度,可以表示几秒、几分钟、几个小时的时间间隔。duration 的原型如下:// 定义于头文件 <chrono>template< class Rep,原创 2021-07-18 18:13:35 · 1559 阅读 · 2 评论 -
C++数值类型和字符串之间的转换
在 C++11 中提供了专门的类型转换函数,程序猿可以非常方便的使用它们进行数值类型和字符串类型之间的转换。数值转换为字符串使用 to_string() 方法可以非常方便地将各种数值类型转换为字符串类型,这是一个重载函,函数声明位于头文件 中,函数原型如下:// 头文件 <string>string to_string (int val);string to_string (long val);string to_string (long long val);string to_原创 2021-07-18 17:29:57 · 422 阅读 · 0 评论 -
C++右值引用
右值C++11增加了一个新的类型,称为右值引用(R-value reference),标记为&&。在介绍右值引用类型之前要了解什么是左值和右值。lvalue是loactor value的缩写,rvalue是read value的缩写左值是指存储在内存中、有明确存储地址(可取地址)的数据右值是指可以提供数据值的数据(不可取地址)通过描述可以看出,区分左值和右值的便捷方法是:可以对表达式取地址(&)就是左值,否则就是右值。所有有名字的变量或对象都是左值,而右值是匿名的。右原创 2021-07-13 00:20:17 · 2174 阅读 · 1 评论 -
C++11基础特性
初始化列表C++11 添加了 initializer_list 类型,允许使用 initializer_list 初始化对象STL 容器例如 map, vector 等都实现了 initalizer_list constructor自定义的对象也可以使用 initalizer_list 作为构造函数的参数class CVector{private: std::vector<int> m_vec;public: CVector() {} CVector(const std原创 2021-07-02 00:03:50 · 181 阅读 · 2 评论 -
结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法
结构体中最后一个成员为[0]长度数组的用法:这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:(1)、不需要初始化,数组名直接就是所在的偏移;(2)、不占任何空间,指针需要占用int长度空间,空数组不占任何空间。“这个数组不占用任何内存”,意味着这样的结构节省空间;“该数组的内存地址就和它后面的元素地址相同”,意味着无需初始化,数组名就是后面元素的地址,直接就能当指针使用。这样的写法最适合制作动态buffer,因为可以这样分配空间malloc(sizeof(structXXX)转载 2021-07-01 00:11:46 · 473 阅读 · 0 评论 -
C/C++中switch用法的一种替换方式
在C/C++中,switch语句是经常被用到的,当switch内的case语句较多时程序有时显得比较繁乱,此种情况下可以用另外一种实现方式替代switch。详细用法见例子:#include "stdafx.h" float AddFunc(float a, float b){ return (a + b);} float SubFunc(float a, float b){ return (a - b);} float MultiplyFunc(float a, float b)转载 2021-07-01 00:09:49 · 916 阅读 · 0 评论 -
C++中指向类成员指针的用法
C++中,指向类的成员指针包含两种:(1).指向类的成员函数的指针:类型 (类名::* 函数成员指针名)(参数表);函数成员指针名 = &类名::函数成员名;class CTest{public: int testAdd(int a, int b) { return a + b; }public: std::string m_str;};int (CTest::* pFunAdd)(int, int);pFunAdd = &CTest::testAdd;原创 2021-06-30 23:47:42 · 1174 阅读 · 0 评论 -
C++ const
const 是 constant 的缩写,本意是不变的,不易改变的意思。在 C++ 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。const修饰普通类型的变量const int a = 7; int b = a; // 正确a = 8; // 错误,不能改变被定义为一个原创 2021-03-14 23:57:44 · 398 阅读 · 0 评论 -
C++基本内置类型
算术类型算术类型分为两类整型(integral type),包括字符和布尔型在内浮点型算术类型的尺寸(该类型数据所占的比特数)在不同机器上有所差别,C++ 标准规定了尺寸的最小值,同时允许编译器赋予这些类型更大的尺寸。某一类型所占的比特数不同,他所能表示的数据范围也不同。类型含义最小尺寸说明bool布尔类型未定义取值为真(true)或假(false)char字符8 位一个 char 的空间应确保可以存放机器基本字符集中任意字符对应的数字值wcha原创 2021-03-14 00:18:46 · 611 阅读 · 0 评论 -
std::exception的使用
std::exception:标准异常类的基类,其类的声明在头文件<exception>中。所有标准库的异常类均继承于此类,因此通过引用类型可以捕获所有标准异常。std::exception类定义了无参构造函数、拷贝构造函数、拷贝赋值运算符、一个虚析构函数和一个名为what的无参虚成员。其中what函数返回一个const char*,该指针指向一个以null结尾的字符数组,并且确保不会抛出任何异常,该字符串的目的是提供关于异常的一些文本信息。除析构函数外,其它函数均通过关键字noexcept原创 2020-09-24 23:29:03 · 5162 阅读 · 0 评论 -
C++11中头文件cmath
<math.h>是C标准函数库中的头文件。在C++中一般用<cmath>。此头文件中声明了一系列函数来计算常见的数学运算和变换:std::abs: 计算绝对值,包括整数类型;std::fabs: 计算绝对值,不包括整数类型;std::fma(x,y,z):x*y+z;std::sin: 正弦;std::asin: 反正弦;std::sinh: 双曲正弦;std::asinh: 双曲反正弦;std::cos: 余弦;std::acos: 反正弦;原创 2020-09-24 23:26:39 · 4792 阅读 · 1 评论 -
C++11中的std::tuple
std::tuple是类似pair的模板。每个pair的成员类型都不相同,但每个pair都恰好有两个成员。不同std::tuple类型的成员类型也不相同,但一个std::tuple可以有任意数量的成员。每个确定的std::tuple类型的成员数目是固定的,但一个std::tuple类型的成员数目可以与另一个std::tuple类型不同。但我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据时,std::tuple是非常有用的。我们可以将std::tuple看作一个”快速而随意原创 2020-09-21 21:39:52 · 11563 阅读 · 2 评论 -
C++11中的正则表达式
正则表达式(regular expression)是计算机科学中的一个概念,又称规则表达式,通常简写为regex、regexp、RE、regexps、regexes、regexen。正则表达式是一种文本模式。正则表达式是强大、便捷、高效的文本处理工具。正则表达式本身,加上如同一门袖珍编程语言的通用模式表示法(general pattern notation),赋予使用者描述和分析文本的能力。配合上特定工具提供的额外支持,正则表达式能够添加、删除、分离、叠加、插入和修整各种类型的文本和数据。完整的正则原创 2020-09-21 21:29:13 · 765 阅读 · 1 评论 -
Lambda表达式
Lambda表达式语法:[capture ] ( params ) mutable exception attribute -> return-type { body }其中capture为定义外部变量是否可见(捕获),若为空,则表示不捕获所有外部变量,即所有外部变量均不可访问,= 表示所有外部变量均以值的形式捕获,在body中访问外部变量时,访问的是外部变量的一个副本,类似函数的值传递,因此在body中对外部变量的修改均不影响外部变量原来的值。& 表示以引用的形式捕获,后面加上需要捕获的原创 2020-09-21 21:27:27 · 340 阅读 · 0 评论 -
C++11中std::function和std::bind
std::function类模版std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等。通过std::function对C++中各种可调用实体(普通函数、Lambda表达式、函数指针、以及其它函数对象等)的封装,形成一个新的可调用的std::function对象,让我们不再纠结那么多的可调用实体。std::function实现了一套类型原创 2020-09-20 22:51:19 · 641 阅读 · 0 评论 -
C++中friend的使用
友元函数并不能看做是类的成员函数,它只是个被声明为类友元的普通函数:(1)、在类里声明一个普通函数,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员。(2)、一个普通函数可以是多个类的友元函数。(3)、一个类的成员函数也可以是另一个类的友元,从而可以使得一个类的成员函数可以操作另一个类的数据成员。(4)、整个类也可以是另一个类的友元,该友元也可以称作为友类。友类的每个成员函数都可以访问另一个类的所有成员。友元声明中声明的函数被视为已使用extern关键字声原创 2020-09-20 16:57:39 · 6226 阅读 · 5 评论 -
C++中函数指针的使用
函数指针是一个指向函数的指针,函数指针表示一个函数的入口地址。指针是变量,所以函数指针也是变量,因此可以使用变量定义的方式来定义函数指针。只是这个指针它不像普通的指针指向一个变量,而它指向的是一个函数,也就是它存储的是一个函数的地址。 在C中,一个函数指针可以多次赋值。取地址符号是可选的,却是推荐使用的。在C++中,对于赋值必须要加”&”,而且还必须在此之前已经定义好了一个类实例,取地址符号要操作于这个类实例的对应的函数成员上。在使用成员函数的指针调用成员函数时,必须要加类实例的...原创 2020-09-20 16:53:29 · 547 阅读 · 0 评论 -
Google C++ 风格指南内容整理
现在很多公司进行C++开发都要求按照Google C++风格。在这个网站http://zh-google-styleguide.readthedocs.org/en/latest/contents/ 有人已经把其翻译成中文。为了便于以后查看,下面的内容完全是来自于这个网站,只是把多个网页的内容整理放在了一起。1.头文件:通常每一个.cc文件都有一个对应的.h文件。也有一些常见例外,如单元测试代码和只包含main()函数的.cc文件。#define保护:所有头文件都应该使用#...原创 2020-09-20 16:20:24 · 399 阅读 · 0 评论 -
编写高质量代码改善C++程序的150个建议
第一部分 语法篇第1章从C继承而来的建议0:不用让main函数返回void main函数的返回类型是int,不是void或其它类型。建议1:区分0的4种面孔(1)、整型0;(2)、空指针NULL,指针与int类型所占空间是一样的,都是32位;(3)、字符串结束标志’\0’;(4)、逻辑FALSE/false,FALSE/TRUE是int类型,而false/true是bool类型。建议2:避免那些由运算符引发的混乱 不要...原创 2020-09-20 15:48:05 · 2520 阅读 · 0 评论 -
DLL动态库导出C++类
使用纯C语言方式头文件//在DLL的工程中定义 DLL_EXPORTS宏(表示导出) 一般直接加到项目配置的 预处理器定义宏中#ifdef DLL_EXPORTS#define DLLAPI __declspec(dllexport)#else#define DLLAPI _declspec(dllimport)#endif//需要导出的类class CTest{public: int add(int a, int b, int c); void relea原创 2020-09-17 00:57:39 · 997 阅读 · 0 评论 -
queue容器
这种存储结构最大的特点是,最先进入 queue 的元素,也可以最先从 queue 中出来,即用此容器适配器存储数据具有“先进先出(简称 "FIFO" )”的特点,因此 queue 又称为队列适配器。queue容器适配器的创建1) 创建一个空的 queue 容器适配器,其底层使用的基础容器选择默认的 deque 容器:std::queue<int> values;通过此行代码,就可以成功创建一个可存储 int 类型元素,底层采用 deque 容器的 queue 容器适配器。2)原创 2020-08-09 14:03:43 · 205 阅读 · 0 评论 -
qmake,make,nmake
gcc是GUN compiler Collection (GUN编译器套件),也可以简单理解为编译器,他可以编译多种语言。make是批处理工具,通过调用makefile文件(抽象层次很低)中的命令来进行多文件编译和链接。maekfile + make可以认为是unix下的项目管理工具。cmake是跨平台的项目管理工具。在windows下会生成visual studio的工程,在Linux下会生成makefile。还可以生成exlipse工程文件。cmake是抽象层次更高的项目管理工具,cmake命令原创 2020-06-30 00:26:08 · 493 阅读 · 0 评论 -
priority_queue 容器
priority_queue 容器适配器模拟的也是队列这种存储结构,即使用此容器适配器存储元素只能“从一端进(称为队尾),从另一端出(称为队头)”,且每次只能访问 priority_queue 中位于队头的元素。但是,priority_queue 容器适配器中元素的存和取,遵循的并不是 “First in,First out”(先入先出)原则,而是“First in,Largest out”原则。直白的翻译,指的就是先进队列的元素并不一定先出队列,而是优先级最大的元素最先出队列。那么,priority原创 2020-06-03 22:38:57 · 404 阅读 · 0 评论 -
queue容器
这种存储结构最大的特点是,最先进入 queue 的元素,也可以最先从 queue 中出来,即用此容器适配器存储数据具有“先进先出(简称 "FIFO" )”的特点,因此 queue 又称为队列适配器。queue容器适配器的创建1) 创建一个空的 queue 容器适配器,其底层使用的基础容器选择默认的 deque 容器:std::queue<int> values;2) 当然,也可以手动指定 queue 容器适配器底层采用的基础容器类型std::queue<int.原创 2020-06-03 22:35:59 · 153 阅读 · 0 评论 -
stack容器
stack容器适配器的创建1) 创建一个不包含任何元素的 stack 适配器,并采用默认的 deque 基础容器:std::stack<int> values;上面这行代码,就成功创建了一个可存储 int 类型元素,底层采用 deque 基础容器的 stack 适配器。2) 上面提到,stack<T,Container=deque<T>> 模板类提供了 2 个参数,通过指定第二个模板类型参数,我们可以使用出 deque 容器外的其它序列式容器,只要该容器支原创 2020-06-02 23:28:57 · 312 阅读 · 0 评论 -
set容器
set 和 multiset 这 2 个容器,它们也属于关联式容器。不过,本节先讲解 set 容器,后续章节再讲解 multiset 容器。和 map、multimap 容器不同,使用 set 容器存储的各个键值对,要求键 key 和值 value 必须相等。基于 set 容器的这种特性,当使用 set 容器存储键值对时,只需要为其提供各键值对中的 value 值(也就是 key 的值)即可。仍以存储上面第 2 组键值对为例,只需要为 set 容器提供 {'a','b','c'} ,该容器即可成功将它.原创 2020-06-02 23:25:22 · 232 阅读 · 0 评论 -
multimap 容器
multimap 容器具有和 map 相同的特性,即 multimap 容器也用于存储 pair<const K, T> 类型的键值对(其中 K 表示键的类型,T 表示值的类型),其中各个键值对的键的值不能做修改;并且,该容器也会自行根据键的大小对存储的所有键值对做排序操作。和 map 容器的区别在于,multimap 容器中可以同时存储多(≥2)个键相同的键值对。创建C++ multimap容器的方法1) 通过调用 multimap 类模板的默认构造函数,可以创建一个空的 mul.原创 2020-06-02 23:20:47 · 342 阅读 · 0 评论 -
map 容器
作为关联式容器的一种,map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括C++基本数据类型(int、double 等)、使用结构体或类自定义的类型。与此同时,在使用 map 容器存储多个键值对时,该容器会自动根据各键值对的键的大小,按照既定的规则进行排序。默认情况下,map 容器选用std::less<T>排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值对做升序排序。当然,根据实际情况的需要,..原创 2020-06-02 23:18:22 · 422 阅读 · 0 评论 -
forward_list
forward_list 是C++11 新添加的一类容器,其底层实现和 list 容器一样,采用的也是链表结构,只不过 forward_list 使用的是单链表,而 list 使用的是双向链表由于单链表没有双向链表那样灵活,因此相比 list 容器,forward_list 容器的功能受到了很多限制。比如,由于单链表只能从前向后遍历,而不支持反向遍历,因此 forward_list 容器只提供前向迭代器,而不是双向迭代器。这意味着,forward_list 容器不具有 rbegin()、rend()..原创 2020-06-02 23:01:27 · 182 阅读 · 0 评论