![](https://img-blog.csdnimg.cn/c8b7dc26d4224d25a9ba78d425ea104e.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
C++
文章平均质量分 82
学习C++
bugcoder-9905
长期更新Java学习笔记
展开
-
【C++】模板为什么不支持分离编译?
事实上编译器是对所有的.cpp文件分开编译的:main.cpp包含test.h,就会将main.cpp和test.h编译成main.o目标文件test.cpp包含test.h,将test.cpp和test.h编译成test.o目标文件然后链接器将main.o和test.o以及一些标准库链接成可执行文件。转载 2023-01-06 23:41:31 · 358 阅读 · 0 评论 -
C++实现一个不能被继承的类
最直观的解决方法就是将其构造函数声明为私有的,这样就可以阻止子类构造对象了。但是这样的话,就无法构造本身的对象了,就无法利用了既然这样,我们又可以想定义一个静态方法来构造类和释放类按照理论分析,这样做确实可以做到防止被继承注意:又有一个新的问题,这种实现原理和单例模式一模一样,就是只能在堆上创建,无法再栈上实现这个类这就是私有的构造函数的局限性主要思想,设计一个模板辅助类Base,将构造函数声明为私有的;再设计一个Base的友元类FinalClass,并且将FinalClass虚继承自Base为什么一定原创 2022-12-07 21:30:38 · 1482 阅读 · 0 评论 -
C++11 move和forward实现原理
因此,在std::forward模板函数中,推断出_Ty的类型为int&&,std::remove_reference用int&& 进行实例化,std::remove_reference的type成员是int,在forward源码中有static_cast,则forward会返回右值引用类型。这时候就发现其实move也没干什么大事,参数是万能引用类型&&,因此经过引用折叠,调用处传入左值,则_Arg是左值引用T&,调用处传入右值,则_Arg是右值引用T&&原创 2022-10-30 21:53:03 · 1589 阅读 · 0 评论 -
C++多继承下,派生类对象有几张虚函数表?
单继承中,基类有虚函数时,派生类会继承其vfptr,如果派生类有重写虚函数,vftable中就会更新重写方法的地址,如果没有重写虚函数,vftable记录的依然是基类中函数的地址。这些东西在编译阶段就生成指令了,哪个类型的基类指针,访问的就是对应的vfptr,找对应的vftable,取虚函数地址。派生类对象有三个vfptr,分别对应于三个基类。原创 2022-10-25 20:37:16 · 490 阅读 · 0 评论 -
C++11条件变量wait函数浅析
从运行结果我们看到,cv的条件a==5时进行了一次notify,然后此时条件不成立,主线程无法解除阻塞,也即下方代码的wait返回后检查while条件不成立,于是继续执行wait,释放锁,等待notify。设置了 Predicate时,只有当 pred 条件为 false 时调用 wait() 才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred 为 true 时才会被解除阻塞。当a>10后,条件成立了,由于这是无法得到子线程的notify,所以主线程会一直wait在cv上。原创 2022-10-24 21:21:09 · 4810 阅读 · 0 评论 -
实现简单的weak_ptr
如果说线程A执行Incref_nz时,获取Uses_的原子值是1,即cnt为1,资源存在,可以将weak_ptr提升成shared_ptr,于是进入while循环。如果线程A调用lock方法,将一个weak_ptr提升成shared_ptr,需要调用My_Ptr_base::_Construct_from_weak,然后执行My_Ref_count_base::Incref_nz增加Uses_引用计数,才能构造新的shared_ptr返回。这样就保证了Incref_nz能正确的将Uses_的原子值+1。原创 2022-09-20 00:34:44 · 797 阅读 · 0 评论 -
实现简单的shared_ptr
类图如下:shared_ptr和weak_ptr都有一个基类Ptr_base,Ptr_base有指向资源的指针_Ptr和指向引用计数的指针_Rep引用计数对象Ref_count封装了对资源以及引用计数对象的释放操作,Ref_count也有一个基类Ref_count_base,封装了对引用计数_Uses、_Weaks,以及对_Uses、_Weaks的++、--操作。原创 2022-09-19 16:05:43 · 624 阅读 · 0 评论 -
什么是迭代器失效问题?
当我们insert或erase后,迭代器底层会将当前迭代器指向容器的指针置空(迭代器不仅要指向容器元素,还有一个成员记录指向的是哪个容器对象),并把操作点到容器末尾的迭代器全部释放(底层会把所有被用户获取的迭代器都用一个链表保存起来,遍历链表,即可释放迭代器),如果我们再操作已经释放的空间或变量,则会报错。当删除88这个元素后,从指向88的迭代器开始,到容器末尾这个区间内,所有的迭代器都失效了(容器开始到删除点区间内迭代器是有效的),再对迭代器操作就会报错。同理,迭代器在第一个insert后就失效了。原创 2022-09-12 12:01:21 · 512 阅读 · 0 评论 -
C++11智能指针weak_ptr
弱引用指针weak_ptr是用来监视shared_ptr的生命周期,是shared_ptr的一个助手。weak_ptr没有重载操作符*和->,因为它不与shared_ptr共享指针,不能操作资源weak_ptr主要是通过lock方法转换成shared_ptr获得资源的监测权,它的构造不会增加引用计数Uses_,它的析构也不会减少引用计数Uses_,纯粹只是作为一个旁观者来监视shared_ptr中管理的资源是否存在。weak_ptr还可以用来返回this指针和解决循环引用的问题。原创 2022-09-07 16:18:06 · 575 阅读 · 0 评论 -
C++11智能指针shared_ptr应用于继承结构
在进行向上转换时,dynamic_cast和static_cast一样,dynamic_pointer_cast和static_pointer_cast一样。但进行向下转换时,dynamic_cast和static_cast不一样,dynamic_pointer_cast和static_pointer_cast也不一样。同样的,我们也可以用支持RTTI的dynamic_pointer_cast对智能指针进行向下转换。我们用支持RTTI的dynamic_cast对裸指针进行向下转换。原创 2022-09-06 21:56:33 · 1003 阅读 · 0 评论 -
C++11智能指针shared_ptr管理动态数组和STL容器
由于使用delete释放空间,就不会查看4字节的元素个数,而把蓝色的4字节空间作为上越界信息,把灰色的越界信息当作头部信息,把fd当成头部信息就会出错了。由于用Int[]初始化shared_ptr的模板类型参数,所以删除器使用delete[],delete[]会在_Ptr往前偏移4字节取出数组元素个数,此时会取出fdfdfdfd,然后执行这么多次析构函数。一般我们不用shared_ptr管理数组,因为我们使用的时候,无法从shared_ptr对象获取数组的长度,很容易越界,且使用不方便。原创 2022-09-06 20:56:08 · 3045 阅读 · 0 评论 -
C++11智能指针shared_ptr介绍和辅助函数
做出一个像Java中垃圾回收器,并且可以运用到所有资源,heap内存和系统资源都可以使用的系统。std::shared_ptr就是C++11推出的解决方案shared_ptr实现了共享所有权(shared ownership)方式来管理资源对象,这意味没有一个特定的std::shared_ptr拥有资源对象。相反,这些指向同一个资源对象的std::shared_ptr相互协作来确保该资源对象在不需要的时候被析构基于共享所有权模式:多个指针能够同时指向同一个资源。原创 2022-09-06 17:58:35 · 828 阅读 · 0 评论 -
C++11智能指针unique_ptr剖析
unique_ptr实现了独享被管理对象指针的概念,这意味着它可以确保一个对象和其对应的资源同一时间只被一个unique_ptr对象拥有。原创 2022-09-05 21:31:17 · 460 阅读 · 0 评论 -
C++ STL总结
一、vector常用函数begin() //返回指向vector首部的迭代器,指向第一个元素end() //返回指向vector尾部的迭代器,并不指向最后一个元素rbegin() //返回指向vector尾部的迭代器,指向最后一个元素rend() //返回指向vector首部的迭代器,并不指向第一个元素pop_back() // 删除最后一个元素,无返回值push_back()......原创 2020-02-23 11:15:12 · 523 阅读 · 0 评论 -
C++11提供STL的emplace方法剖析二
如果给emplace_back传入的右值,则Types是Test&&,引用折叠后args就是Test&&如果给emplace_back传入的左值,则Types是Test&,引用折叠后args就是Test&基于可变参模板和引用折叠的emplace_back。使用空间配置器和可变参模板的vector。空间配置器Allocator。.........原创 2022-08-30 20:45:30 · 486 阅读 · 0 评论 -
C++11提供STL的emplace方法剖析一
对于emplace而言,如果传入要构建Test对象所需要的参数(构造函数的参数),就会直接在vector底层构造对象,不会产生额外的临时对象。而对于push_back来说,是先构造出临时对象,再进行拷贝构造。如果是插入对象,不管是左值还是右值,都需要先调用构造函数生成对象,再调用拷贝构造在容器底层空间构造对象。如果直接插入对象,emplace_back和push_back是没有区别的,都是对象的调用拷贝构造。......原创 2022-08-30 18:01:16 · 348 阅读 · 0 评论 -
用C++11 make_shared替代shared_ptr
用make_shared的原理如图,代码上不会再看见显式的new运算符,我们如果调用shared_ptr构造函数时,会手动new一次资源,shared_ptr的构造函数又会new一个引用计数的对象,如果两次new不能都成功,就会有资源泄露。执行成功了,而shared_ptr的构造函数执行失败了,就不会有引用计数的_Ref_count_base对象,就意味着不存在shared_ptr对象,就不会调用shared_ptr的析构函数,那我们new出来的堆区资源也就不会释放了。申请空间效率高,防止了资源泄露。...原创 2022-08-30 16:31:22 · 471 阅读 · 0 评论 -
C++11 move移动语义和forward类型完美转发
一个自定义空间配置器的vector当push_back方法的参数是一个临时对象时,我们希望匹配带右值引用参数的push_back,直接把临时对象的资源转移到vector数组中,并将临时对象指向资源的指针置为nullptrvector类添加带右值引用参数的push_back空间配置器添加带右值引用参数的constructString类定义见下方完整代码虽然"123"调用普通构造函数生成的String是一个右值,匹配的也是带右值引用参数的push_back,但右值引用变量实际上是一个左值,push_ba原创 2022-06-10 13:41:07 · 177 阅读 · 0 评论 -
C++11 左值和右值
通俗来讲,左值就是有名字有内存的量;右值就是没有名字的,比如函数返回的时候,有可能会在调用函数栈帧上构造的临时量,或者是没内存的,比如1、"hello"等左值引用不能引用右值const左值引用可以引用右值右值引用可以引用右值const左值引用和右值引用的汇编指令如下:不管const左值引用,还是右值引用,都是先开辟一块空间,把值拷贝到该空间,然后引用会指向这个地址const左值引用是不能修改值的,而右值引用可以修改值,如下:一个右值引用变量,本身是一个左值,有内存有名字一个左原创 2022-06-09 22:27:35 · 707 阅读 · 0 评论 -
详解C++11 RAII机制
什么是RAII?RAII是Resource Acquisition Is Initialization(wiki上面翻译成 “资源获取就是初始化”)的简称,是C++语言的一种管理资源、避免泄漏的惯用法。利用的就是C++构造的对象最终会被销毁的原则。RAII的做法是使用一个对象,在其构造时获取对应的资源,在对象生命期内控制对资源的访问,使之始终保持有效,最后在对象析构的时候,释放构造时获取的资源。为什么要使用RAII?上面说到RAII是用来管理资源、避免资源泄漏的方法。那么,用了这么久了,也写了这么多程序了,转载 2022-06-08 17:10:01 · 3251 阅读 · 0 评论 -
decltype类型推导
decltype 是 C++11 新增的一个关键字,它和 auto 的功能一样,都用来在编译时期进行自动类型推导既然已经有了 auto 关键字,为什么还需要 decltype 关键字呢?因为 auto 并不适用于所有的自动类型推导场景,在某些特殊情况下 auto 用起来非常不方便,甚至压根无法使用,所以 decltype 关键字也被引入到 C++11 中auto 和 decltype 关键字都可以自动推导出变量的类型,但它们的用法是有区别的:其中,varname 表示变量名,value 表示赋给变量的值转载 2022-06-08 16:14:05 · 581 阅读 · 1 评论 -
C++11 auto类型推导
在 C++11 之前的版本(C++98 和 C++ 03)中,定义变量或者声明变量之前都必须指明它的类型,比如 int、char 等;但是在一些比较灵活的语言中,比如 C#、JavaScript、PHP、Python 等,程序员在定义变量时可以不指明具体的类型,而是让编译器(或者解释器)自己去推导,这就让代码的编写更加方便。C++11 为了顺应这种趋势也开始支持自动类型推导了!C++11 使用 auto 关键字来支持自动类型推导。在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 sta转载 2022-06-04 10:22:30 · 184 阅读 · 0 评论 -
理解malloc、free、new、delete
malloc和new的区别malloc是按字节开辟空间的,new开辟内存时需要指定类型(new int()),malloc开辟内存返回的都是void*,而new返回的是对应类型的指针malloc负责开辟空间,new不仅有malloc的功能,还可以进行数据初始化和构造对象,比如:new int(10)。new有开辟空间和构造的功能。malloc开辟内存失败返回nullptr,而new则会抛出bad_alloc异常我们调用new实际上是调用的operator new,可以重载operat原创 2022-05-17 11:32:11 · 767 阅读 · 0 评论 -
C++语言级别四种类型转换
文章目录一、const_cast二、static_cast三、reinterpret_cast四、dynamic_castC语言中的强制类型转换通常不安全,根据强转的类型造成变量内存扩大或缩小,访问不安全const_cast : 去掉(指针或者引用)常量属性的一个类型转换,只能转换指针或引用类型static_cast : 提供编译器认为安全的类型转换(没有任何联系的类型之间的转换就被否定了,就编译不通过)reinterpret_cast : 类似于C风格的强制类型转换,谈不上什么安全dynami原创 2022-05-16 16:12:28 · 842 阅读 · 0 评论 -
海量数据求top K
文章目录一、大根堆/小根堆二、快排分割三、海量数据查重和topK的综合应用1. 题目1:数据的重复次数最大/最小的前K个/第K个2. 题目2:有一个大文件,内存限制200M,求文件中重复次数最多的前10个top K问题:给定10000个整数,找出前10大的元素一、大根堆/小根堆先用前10个整数创建一个小根堆(最小值就在堆顶),然后遍历剩下的整数,如果整数比堆顶元素大,那么堆顶元素出堆,然后再把整数入堆,遍历完所有整数,小根堆里面放的就是值最大的前10个元素了大根堆淘汰大的,用于找top K小的;原创 2022-05-12 21:32:52 · 279 阅读 · 0 评论 -
海量数据哈希表查重
文章目录一、海量数据的查重问题二、无限制哈希表查重(重复出现的数字、重复出现的次数、第几个重复)三、内存限制哈希表查重(重复出现的数字以及出现的次数)四、哈希表unordered_set查重(第几个重复)五、位图查重(第几个重复)查重:数据是否有重复,以及数据重复的次数topK:有几亿个数字。求元素的值,前K大/小,第K大/小去重:去掉重复多次的数字,数字只保留一份一、海量数据的查重问题哈希表:得看有没有对内存的限制,如果没有限制,就是直接用哈希表解决。比如说 50亿(5G)个整数的查重问题原创 2022-05-12 17:14:26 · 874 阅读 · 0 评论 -
DFS/BFS搜索迷宫路径
文章目录一、DFS搜索迷宫路径二、BFS搜索迷宫路径一、DFS搜索迷宫路径DFS依赖栈结构先把左上角节点入栈,然后依次查看栈顶元素的右、下、左、上四个方向是否可以走,如果能走就把节点入栈,然后再依次查看依次查看栈顶元素的右、下、左、上四个方向;如果四个方向都不能走,就把栈顶元素出栈最终栈空,则说明退回到了左上角的节点;右下角的节点入栈,则表示找到了出口需要注意的是,每入栈一个节点:需要将当前节点到入栈节点的方向置为NO,保证如果走进死胡同回退后,不会再次往这个错误的方向走需要将刚入栈节原创 2022-05-11 21:23:47 · 1401 阅读 · 0 评论 -
C++智能指针的enable_shared_from_this和shared_from_this机制
文章目录一、问题代码1. 错误代码一2. 错误代码二二、shared_ptr原理分析三、问题解决1. 错误代码一修改2. 错误代码二修改如果不熟悉C++带引用计数的智能指针shared_ptr和weak_ptr,请参考我的另一篇介绍智能指针的博客: https://blog.csdn.net/QIANGWEIYUAN/article/details/88562935鉴于同学们提问的一些有关智能指针的问题,这篇文章主要介绍C++11提供的智能指针相关的enable_shared_from_this和sha转载 2022-05-11 16:07:15 · 923 阅读 · 0 评论 -
C++ STL容器空间配置器详解
文章目录一、一个简单的vector容器二、不使用空间配置器存在的问题三、使用空间配置器一、一个简单的vector容器模拟实现一个简单的vector容器#include <iostream>using namespace std;const int INIT_SIZE = 10;template<typename T>class vector {public: vector(int size = INIT_SIZE) { first_ = new T[si原创 2022-05-11 15:17:48 · 654 阅读 · 0 评论 -
C++设计模式总结
一、单例模式一个类不管常见多少次对象,永远只能得到该类型一个对象的实例// p1、p2、p3指向同一对象A* p1 = new A();A* p2 = new A();A* p3 = new A();饿汉式单例模式: 还没有获取实例对象,实例对象就已经产生了优点:线程安全。对象存放在数据段,main函数还没有开始执行,对象就已经初始化好了,一定是线程安全的。缺点: 获取在软件启动的时候,并没有使用到这个对象,然而这个对象已经产生,这就比较浪费资源。#include<iostream原创 2021-09-06 21:30:38 · 4426 阅读 · 1 评论 -
C++智能指针
一、基础知识介绍二、不带引用计数的智能指针三、带引用计数的智能指针四、shared_ptr 和 weak_ptr五、多线程访问共享对象的线程安全问题六、自定义删除器原创 2021-08-27 20:28:59 · 1347 阅读 · 6 评论 -
C++对象优化
文章目录一、函数对象优化一、函数对象优化#include <iostream>using namespace std;class Test {public: Test(int a = 10) :ma(a) { cout << "Test(int)" << endl; } Test(const Test& src):ma(src.ma) { cout << "Test(const Test& src)" <<原创 2021-08-24 10:31:42 · 214 阅读 · 1 评论 -
C++11语言级别的多线程编程
文章目录一、多线程类thread二、线程互斥锁mutex三、生产者—消费者模型一、多线程类threadC++语言层面thread,其实底层还是调用操作系统对象的多线程函数,例如windows下调用createThread,linux下调用的是pthread_create。语言层面的支持就做到了跨平台编译运行。thread示例代码:#include <iostream>#include <thread>using namespace std;void fun(stri原创 2021-08-31 12:07:37 · 761 阅读 · 0 评论 -
C++ function函数对象和bind绑定器以及lambda表达式
一、bind1st和bind2ndbind可用于给多元函数对象降元:bind + 二元函数对象 = 一元函数对象/*find_if需要一个一元函数对象作为参数,而greater是二元函数对象,这就需要用到绑定器greater : a > bless : a < b*/auto iter = find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 70)); // 返回第一个小于70的元素的位置底层实现原理#i原创 2021-08-30 19:27:28 · 366 阅读 · 0 评论 -
C++校招常见问题汇总
文章目录1. this指针干什么用的?2. new和delete,什么时候用new[]申请,可以用delete释放?3. static关键字的作用(从elf结构、链接过程回答)?4. C++的继承有什么好处?5. 讲一下C++的多态6. 空间配置器allocator?7. vector和list的区别?8. map和multimap的区别?9. C++如何防止内存泄漏?智能指针详述10. C++如何调用C语言函数接口?11. 那些情况下可能出现访问越界12. C++中类的初始化列表13. C和C++的区别以原创 2021-09-10 18:33:28 · 969 阅读 · 0 评论 -
深度剖析SGI STL二级空间配置器内存池源码
文章目录一、SGI STL二级空间配置器重要成员解读1. 二级空间配置器内存池的结构2. 两个重要的函数(1) _S_round_up(2)_S_freelist_index3. 内存池allocate分配过程一、SGI STL二级空间配置器重要成员解读SGI STL包含了一级空间配置器和二级空间配置器其中一级空间配置器allocator采用malloc和free来管理内存,和C++标准库中提供的allocator是一样的但其二级空间配置器allocator采用了基于freelist自由链表原理的原创 2021-11-11 21:54:46 · 1165 阅读 · 2 评论 -
C和C++的区别(引用&)
一、关于inline函数内联函数:在 编译期 的时候,内联函数的代码会在 调用的地方展开,没有函数栈帧的开辟inline函数编译期间在代码调用的地方展开,有逻辑性的尽心那个替换能够调试,在debug版本inline函数和普通的函数表现一致只有在release版本才会真正在调用点展开因为需要在编译期间展开,而编译期间针对的是单文件所以,inline函数的作用域只在本文件,debug版本生成local符号有类型检测,安全宏函数预编译期展开在代码调用点,进行简单的文字替换,不能调试原创 2021-06-27 22:39:50 · 1006 阅读 · 7 评论 -
C++继承和多态总结
文章目录一、继承的本质和原理一、继承的本质和原理总结:外部只能访问对象public成员,protected和private的成员无法直接访问在继承结构中,派生类可以继承基类的private成员,但是无法直接访问protected和private的区别:在基类中定义的成员,想被派生类访问但是不想被外部访问,那把基类中的相关成员定义成protected。如果派生类和外部都不访问,那就把基类中的相关成员定义成peivate使用class定义派生类,默认继承方式是private;使用struct定义原创 2021-08-10 12:46:22 · 827 阅读 · 0 评论 -
C++运算符重载
#include<iostream>using namespace std;class Plural {private: int _real; int _vir;public: Plural():_real(int()),_vir(int()) { cout << "Plural()" << endl; } Plural(int real, int vir) { _real = real; _vir = vir; cout <原创 2021-07-27 15:02:53 · 400 阅读 · 1 评论 -
C++面向对象笔记
分为七个#include<iostream>using namespace std;class Person {private: char* _name; int _age; static int _num;public: Person(const char* name, int age) { this->_age = age; // 深拷贝 this->_name = new char[strlen(name) + 1]; strcpy_原创 2021-07-21 15:20:52 · 216 阅读 · 1 评论