
C++
文章平均质量分 88
国服卤蛋儿
这个作者很懒,什么都没留下…
展开
-
C++两种枚举类型-限定作用域的枚举类型 和 不限定作用域的枚举型别
C++包含两种枚举类型:限定作用域的枚举类型不限定作用域的枚举型别带限定作用域的枚举型别通过enum class声明,不限定作用域的枚举型别通过enum声明.1、不限定作用域的枚举型别可能导致枚举量泄漏到所在的作用域空间namespace TestSpace {enum Color { red = 0, green, blue,};auto red = true; // 错误}; // namespace TestSpace在同一个作用域中,定义了不限定作用域的枚原创 2021-02-27 20:15:16 · 3971 阅读 · 0 评论 -
单例模式
????意图单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。????问题单例模式同时解决了两个问题, 所以违反了_单一职责原则_:保证一个类只有一个实例。 为什么会有人想要控制一个类所拥有的实例数量? 最常见的原因是控制某些共享资源 (例如数据库或文件)的访问权限。它的运作方式是这样的: 如果你创建了一个对象, 同时过一会儿后你决定再创建一个新对象, 此时你会获得之前已创建的对象,而不是一个新对象。注意, 普通构造函数无法实现上述行为,原创 2020-10-08 16:54:07 · 333 阅读 · 2 评论 -
C++中获取数组的长度
1. 算术表达式:#include <iostream> int main() { int arr[4]; std::cout << sizeof( arr ) / sizeof( arr[0] ) << std::endl; // 输出4}注:数组形参和指针形参的方式传递数组,会有指针降级,即不能在自定义内部通过sizeof( arr ) / sizeof( arr[0] )的方式获取数组元素个数2. 函数模板参数自动推断:#includ原创 2020-08-30 13:34:10 · 1154 阅读 · 0 评论 -
json解析之C++库nlohmann / json
测试:https://wandbox.org/permlink/3lCHrFUZANONKv7a项目地址:https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent/blob/master/include/nlohmann/json.hpp设计目标直观的语法。在像Python这样的语言中,JSON就像是一个一流的数据类型。我们使用了现代C++的所有操作符魔法,在您的代码中实现了相同的感觉。查看以下示例你会明白我的意思。原创 2020-08-27 12:20:45 · 17016 阅读 · 7 评论 -
虚指针和虚表
所以当用sizeof来获取含有虚函数的类的大小的时候,会发现结果 比 里面还有的数据 大4个字节。这四个字节就是(虚)指针。(32位系统)子类里面有父类的成员变量。当然,父类有虚函数,自然 子类 就有虚函数。虚表里放的都是虚函数的指针,指向虚函数的地址。子类即使没有重写 父类的 虚函数, 子类的虚表里 也有虚函数,只不过是父类的虚函数。如上图中,B类没有重写 A类的 虚函数 vfun2(),那么B的虚表里的虚函数的指针就是和A类的那个虚函数指针相同的。调用虚函数,走的路线是:通过类的虚指针.原创 2020-08-03 22:44:38 · 477 阅读 · 0 评论 -
快排非递归实现 + 算法可视化网站
算法可视化网站:https://visualgo.net/zh/支持搜索:快速排序 非递归实现:void quickSortNonRecursive(vector<int> &nums, int low, int height){ stack<int> s; if (low<height) { int mid = getPartition(nums, low, height); if (mid-1>l原创 2020-08-03 22:01:54 · 218 阅读 · 0 评论 -
string
string 是 C++ 中常用的一个类。使用 string 类需要包含头文件,下面的例子介绍了几种定义 string 变量(对象)的方法:初始化#include <iostream>#include <string>using namespace std;int main(){ string s1; string s2 = "c plus plus"; string s3 = s2; string s4 (5, 's'); ret原创 2020-08-03 15:01:48 · 211 阅读 · 0 评论 -
转换函数 和 explicit
此时就不需要重载全局操作符+。首先是检查有没有全局重载对应的+,没有找到,再调用转换函数,如果没有则报错,有的调用其进行隐式转换。转换函数语法:返回类型就是double,所以不用写。所以转换函数不用写返回类型。另外呢,一般都加const(建议加)。(当然不加也可以编译通过)注:上图中的转换函数有问题,应该先将分子分母转成double再运算返回:#include <iostream>using namespace std;class Fraction{public: .原创 2020-08-03 13:16:59 · 181 阅读 · 0 评论 -
const成员变量和成员函数
const成员变量const 成员变量的用法和普通 const 变量的用法相似,只需要在声明时加上 const 关键字。初始化 const 成员变量只有一种方法,就是通过构造函数的初始化列表。初始化 const 成员变量构造函数初始化列表还有一个很重要的作用,那就是初始化 const 成员变量。初始化 const 成员变量的唯一方法就是使用初始化列表。例如 VS/VC 不支持变长数组(数组长度不能是变量),我们自己定义了一个 VLA 类,用于模拟变长数组:class VLA{private:原创 2020-08-03 12:15:36 · 366 阅读 · 0 评论 -
虚函数 和多态
继承 搭配 虚函数成员函数前 加virtual函数的继承 继承的是调用权。虚函数:希望对子类 重新定义(override重写),且已有默认定义纯虚函数:一定要重新定义。纯虚函数是可以有定义的。相关设计委托与继承的设计模式功能最强大的一种。关系:这是一种Observer的设计模式,适用于如有一份文件,多个窗口查看或者一份数据,有多种视图显示;;示例中Subject是数据类,Observer是显示类,可以被多个observer继承实现不同方式的查看。这种解法叫做 composi原创 2020-08-03 11:09:09 · 145 阅读 · 0 评论 -
关于 复合 和 继承 和 委托
复合的例子:为何不用继承?因为用继承的话,父类的接口仍然可以调用。所以这里 使用所谓的 组合,所谓的适配器Adapter就是这样实现的:这样组合起来,底层容器是deque,queue可以调用deque的接口去完成自己的接口,而deque里多于的接口,queue是希望屏蔽掉的。而这个的组合,就使得deque的接口没有暴露在外,而继承则会使得deque的接口可以使用。...原创 2020-08-02 22:18:19 · 228 阅读 · 0 评论 -
关于static
复习一下static成员变量和成员函数静态成员变量有时候我们希望在多个对象之间共享数据,对象 a 改变了某份数据后对象 b 可以检测到。共享数据的典型使用场景是计数,以Student 类为例,如果我们想知道班级中共有多少名学生,就可以设置一份共享的变量,每次创建对象时让该变量加 1。class Student{public: Student(char *name, int age, float score); void show();public: static int .原创 2020-08-02 21:33:13 · 248 阅读 · 0 评论 -
一个inline关键字引发的错误
这个问题找了好久,没找出原因。复习C++时候,写了个小程序,没想到编译出了错:main.cpp /**************** main.cpp ***************************/#include <iostream>#include "QzxString.h"using namespace qzx;int main() { QzxString s1; QzxString s2("hello"); QzxString s3(s2原创 2020-08-02 13:51:08 · 978 阅读 · 0 评论 -
关于C++模板继承的注意点
如另一篇文章里所说:error: there are no arguments to ‘size‘ that depend on a template parameter, so a declaration of ‘si_qq_26189301的博客-优快云博客我在使用编写Stack类模板的时候,继承了自定义的Vector模板类。然而在编译的时候出错了。编译在编译的时候,一开始使用的VS的编译器,运行正常,没有问题。当换成gnu的编译器时,编译出错了。完整错误信息如下:百思不得其解。看前原创 2020-07-30 14:26:57 · 1015 阅读 · 4 评论 -
error: there are no arguments to ‘size‘ that depend on a template parameter, so a declaration of ‘si
完整的错误:error: there are no arguments to ‘size’ that depend on a templateparameter, so a declaration of ‘size’ must be available [-fpermissive]T pop() { return remove ( size() - 1 ); }这是在使用之前编译通过的Vector模板类后,新建栈类 Stack 对Vecor公有继承。然而,在Stack中使用Vector的pub原创 2020-07-29 12:01:44 · 2746 阅读 · 2 评论 -
STL -- deque深度探索
STL之deque实现详解_一个菜鸟的博客-优快云博客_stl deque https://blog.youkuaiyun.com/u010710458/article/details/79540505双端队列 /dek/buffer 或者 称为 nodedeque是分段连续。对外号称连续(显现出来的特性),实际不然。何为dequedeque是双向开口的连续线性空间(动态将多个连续空间通过指针数组接合在一起),随时可以增加一段新的空间,所以数据想vector里面的分配,复制,释放操作不会发生。dequ原创 2020-07-29 15:28:29 · 178 阅读 · 0 评论 -
STL -- array深度探索 + 迭代器类型
为什么要把数组这样包装呢?不包装的话,算法就不能使用数组这样的形式了,将数组排除在外了。因为算法需要对询问迭代器的五种关联类型。包装后 算法就可以选择最优的迭代器来实行算法why?不需要包装把??前面不是有Iterator Traits吗?用这个不就使用普通指针作为退化的迭代器了从而使用算法<algorithm>了? 是因为需要选择最优的迭代器吗?普通的指针不就是所谓的 随机访问迭代器么?关于迭代器分类按照定义分类:按功能分类:另外,关于输入和输出迭代器:输入迭代器:原创 2020-07-29 15:28:07 · 135 阅读 · 0 评论 -
STL - vector深度探索
看一看到protected部分有三个指针(迭代器),所以sizeof(vector<T>) 为3*4=12 (32为系统为12 64位系统为 24)注意sizeof(vector<bool>)是一个偏特化版本,实现不同,sizeof(vector<bool>) 为 40 (64位系统验证)为什么内存不足后,调用insert_aux()函数还需要又重复做一次检查呢?不是多此一举吗?是因为insert_aux()还会被其他函数调用,其他的情况下需要检查。(aux.原创 2020-07-29 15:27:18 · 198 阅读 · 0 评论 -
STL -- __iterator_traits
__iterator_traits技法用于模板编程,STL所有算法都是基于模板实现的。特殊的特化:特化为指针 或 引用STL中的例子: 特化为指针 和 底层指针(引用?)://这段代码是STL源码中的一部分template <class Iterator>struct iterator_traits { typedef typename Iterator::iterator_category iterator_category; typedef typename Iterat原创 2020-07-29 15:05:19 · 172 阅读 · 0 评论 -
STL -关于迭代器的设计原则和 Iterater Traits 的作用和设计
Iterater Traits理解为 用于萃取 所需的特征有的迭代器只能往前,有的只能往后,有的只能加1 ,有的只能-1,有的可以随机读取(+n或-n)这就叫做 种类 category迭代器必须能 回到出 算法的 5种提问:迭代器类型Iterator_category,距离 difference_type,元素值类型value_type,另外,指针(pointer)和引用(reference)在STL中从未被使用这5种typedef 即相关类型 associated types...原创 2020-07-29 15:25:58 · 150 阅读 · 0 评论 -
(环状)双向链表 源码解析
list本身就是一个node ,一个指针, 一个节点这里是gnuC 2.9版本除了绿色的数据本身,还要附带两个指针这里的指针是void_pointer类型 , 即 void*可以运作,但是不够好,在学校老师会给你扣一分。所以在程序设计里还需要转型。为何不用 __list_node *.后面知道,在gnu 4.9版本确实有改善。尾节点所有容器表现头尾时候,是前闭后开区间4.9版本的实现中去掉了尾节点中的数据域。迭代器:这里的迭代器 不能是指针,因为list是不连续的内存空间。所有容器.原创 2020-07-29 15:25:29 · 204 阅读 · 0 评论 -
容器与分类
左右两侧的数值:一个容器的大小。(跟容器里有多少个元素没有关系)(代表容器本身大小)下面是名称原创 2020-07-29 15:24:55 · 156 阅读 · 0 评论 -
分配器allocator
内存分配不管怎样,最终底层都会调用到c库的 malloc()函数,然后再根据操作系统的不同区调用更底层的部分上图左上角 VC中,源代码可以看到 new是调用malloc的。malloc真正给你的部分是下图这样的 :蓝色的部分你懂的 :void *malloc(size_t size)size是内存块的大小,字节为单位上下的红色是cookie绿色部分是调整到某个边界。这些细节在侯老师的课《内存管理》中会介绍?所以malloc给你的比你申请的大小还多了不少东西。附加的东西是基本不变原创 2020-07-29 15:24:39 · 216 阅读 · 0 评论 -
函数模板 和 普通函数 和 特化函数模板 -- 调用顺序 和正确性
使用的在线运行工具:https://tool.lu/coderunner/?t=1595757114/// 模版特化#include <iostream>#include <cstring> //strcmpusing namespace std;template <class T>int compare(const T left, const T right){ std::cout <<"in template <class原创 2020-07-29 15:23:43 · 493 阅读 · 0 评论 -
C++ 模板的定义、使用及特化
1、模板函数模板函数的定义格式:template <class 形参名1,class 形参名2...,class 形参名3> //这里class也可以换为typename返回值类型 函数名(){...}template <class T>bool Isequal(T &a, T &b){ return a == b;}int main(){ string s1("hello"); string s2 = s1;原创 2020-07-29 15:26:19 · 643 阅读 · 0 评论 -
模板 泛化 全特化 偏特化
template<>出现,就表示要特化了为什么要特化呢?泛化不就是为了解决数据类型不一致吗?泛化是通用,特化是优化,缺一不可特化,又被成为全特化 full-specialization偏特化 Partial specialization接受两个模板参数,绑定其中一个模板参数,变成只有一个了(比如关联式容器)vector<bool>是一个特化版本。特化函数模板能被重载,而类模板不可以,我们可以通过特化来实现相似的效果,从而可以透明地获得具有更高效率的代码。..原创 2020-07-29 15:25:48 · 980 阅读 · 0 评论 -
操作符重载
https://zh.cppreference.com/w/cpp/language/operatorshttps://en.cppreference.com/w/cpp/language/operators原创 2020-07-29 15:23:18 · 86 阅读 · 0 评论 -
关于命名空间
每个命名空间都是一个作用域::和其它作用域类似,命名空间中的每个名字都必须表示该空间内的唯一实体。因为不同命名空间的作用域不同,所以在不同命名空间内可以有相同名字的成员。定义在某个命名空间中的名字可以被该命名空间内的其它成员直接访问,也可以被这些成员内嵌作用域中的任何单位访问。位于该命名空间之外的代码则必须明确指出所用的名字属于哪个命名空间。命名空间可以是不连续的:命名空间可以定义在几个不同的部分,这一点与其它作用域不太一样。命名空间的定义可以不连续的特性使得我们可以将几个独立的接口和实现文件组成一个命原创 2020-07-29 15:01:55 · 210 阅读 · 0 评论 -
关于多态 -一点tag
多态部分,基类使用虚析构函数。将动态申请的派生类对象指针赋给基类指针。最后在调用delete释放基类指针指向的内存的时候,不仅会调用派生类的析构函数,也会调用基类的析构函数。这就与普通的虚成员函数不一样,普通的虚成员函数调用只会调用派生类的成员函数,而不会调用基类的成员函数。如下面的演示程序所示:#include <iostream>using namespace std; class Base{public: Base(){} virtual fun(int a){原创 2020-07-25 19:36:36 · 87 阅读 · 0 评论 -
关于新旧式 头文件
C++ 引入了命名空间的概念,计划重新编写库,将类、函数、宏等都统一纳入一个命名空间,这个命名空间的名字就是std。std 是 standard 的缩写,意思是“标准命名空间”。但是这时已经有很多用老式 C++ 开发的程序了,它们的代码中并没有使用命名空间,直接修改原来的库会带来一个很严重的后果:程序员会因为不愿花费大量时间修改老式代码而极力反抗,拒绝使用新标准的 C++ 代码。C++ 开发人员想了一个好办法,保留原来的库和头文件,它们在 C++ 中可以继续使用,然后再把原来的库复制一份,在此基础上稍加原创 2020-07-29 15:02:29 · 158 阅读 · 0 评论 -
扩容策略
递增式扩容?每次递增一个固定的容量数值_elem = new T [_capacity + INCREASEMENT]最坏情况:在初始容量0的空向量中,连续插入n=m*INCREASEMENT >>2个元素(n足够大,m组increament)于是,在第1,I+1,2I+1…处插入时,都需要扩容。总共m次扩容。时间成本:总体耗时:加倍式扩容?_elem = new T [_capacity << 1 ]最坏情况:在初始容量1的满向量中,连续插入n=2^m原创 2020-07-24 16:04:31 · 340 阅读 · 0 评论 -
关闭优化选项
这里没有调用拷贝构造函数,按照C++机制,应该是会调用的。。。想起来 ,以前最初写拷贝构造函数的时候也是跟预想的调用不一致。记得编译器会自动优化掉临时对象的。比如 在一个函数中 return list(); 本应该会因为创建临时对象而调用拷贝构造函数,但是编译器会优化掉临时对象,从而在最终结果里无法看到临时对象的拷贝构造与析构。所以加优化选项来查看结果。在编译选项中添加 -fno-elide-constructorsCMAKELISTS文件中添加编译选项的方法有:1)add_compile.原创 2020-07-23 22:19:44 · 4047 阅读 · 0 评论 -
initialized list
对象初始化方法有很多种,请看下面的代码://初始化列表int i_arr[3] = { 1, 2, 3 }; //普通数组struct A{ int x; struct B { int i; int j; } b;} a = { 1, { 2, 3 } }; //POD类型//拷贝初始化(copy-initialization)int i = 0;class Foo{ public: Foo(int) {}原创 2020-07-29 15:04:27 · 365 阅读 · 0 评论 -
C++: most vexing parse(语法解析)
(令人头痛的语法解析)(这样的问题感觉很难发现,尤其在项目相对复杂的时候。。平时应该如何避免呢)在写C++的时候遇到一个问题,初始化一个对象的时候构造函数没有被调用。类似的代码如下:#include <iostream>#include <string>using std::cout;using std::endl;class A { public: A(int num){ m_num=num; cout << "构造原创 2020-06-13 20:58:36 · 774 阅读 · 0 评论 -
VS2017一未将对象引用设置到对象的实例
VS2017刚新建项目就出现未将对象引用设置到对象的实例的错误。系统是win10专业版,VS是官方镜像自定义安装的,安装的时候没出错,然后一新建项目就报错,“未将对象引用设置到对象的实例”,修复,卸载重装,没用。看到知乎一个回答:VS2015一新建项目就出现未将对象引用设置到对象的实例怎么办? - 知乎 https://www.zhihu.com/question/37119592该回答...原创 2019-12-02 22:29:51 · 8436 阅读 · 1 评论 -
关于C++头文件
关于C++头文件.h的工作原理一、C++编译模式通常,在一个C++程序中,只包含两类文件——.cpp文件和.h文件。其中,.cpp文件被称作C++源文件,里面放的都是C++的源代码;而.h文件则被称作C++头文件,里面放的也是C++的源代码。C+ +语言支持“分别编译”(separate compilation)。也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的.cpp文件里。...转载 2019-10-23 13:26:20 · 195 阅读 · 0 评论 -
关于C风格字符串的一些问题
这里写自定义目录标题问题来源问题的探究问题解决问题来源今天在阅读C++primer第五版的第197页时,谈到向main函数传递命令行参数,书中的说明是这样的:然而我想,这里argv应该是一个数组吗,它的元素不应该是是指向字符的指针吗?但实际上按照书上的说明,argv是一个数组,它的元素是指向C风格字符串的指针问题的探究然后我开始百度不少网页和博客,都没找到什么说明,一篇稍微相关的文章这...原创 2019-08-20 16:41:37 · 251 阅读 · 1 评论 -
含有可变形参的函数
为了编写能处理不同数量实参的函数,C++11提供了两种主要方法:若所有实参类型相同,则恶意传递一个名为initializer_list的标准库类型:若实参类型不同,可以编写一种也输的函数(所谓的可变参数模板,本文不做介绍)。参考文章:C++11 initializer_list形参...原创 2019-08-20 16:54:46 · 297 阅读 · 0 评论