c++入门到进阶
文章平均质量分 86
适合有一定的c语言基础,逐步了解c++的特性,并使用c++上手项目
稻草人敲代码
懒得写简介
展开
-
【智能指针】智能指针的使用及其原理
构造时传递给SmartPtr一个指向资源的指针,之后我们就不用再显式的释放资源了,因为SmartPtr会自动帮我们释放。前两种智能指针实际上没有很好的解决智能指针之间的拷贝问题,于是C++11又设计了另一种可以支持拷贝且不会造成指针悬空的智能指针,即。为了专门解决shared_ptr的循环引用问题,C++11又提供了一种weak_ptr的智能指针。支持拷贝构造和赋值构造,从管理角度来说,拷贝一个智能指针其实就是将资源管理权交给另一个。对象来说,它的内置资源指针就悬空了。,就像指向资源的指针一样。原创 2024-07-22 17:30:36 · 1125 阅读 · 0 评论 -
【C++异常】异常的使用及其原理
如果Division发出的异常Func函数没有捕捉到,此时会马上退回到main函数的栈中,原创 2024-07-22 14:56:47 · 975 阅读 · 0 评论 -
【C++11常见新特性(三)】线程库
在构造(或移动(move)赋值)时,unique_lock 对象需要传递一个 Mutex 对象作为它的参数,新创建的 unique_lock 对象负责传入的 Mutex 对象的上锁和解锁操作。比如:一个线程对变量number进行加一100次,另外一个减一100次,每次操作加一或者减一之后,输出number的结果,要求:number最后的值为1。注意:原子类型通常属于"资源型"数据,多个线程只能访问单个原子类型的拷贝,因此在C++11中,原子类型只能从其模板参数中进行构造,,从而产生编译错误或运行时错误。原创 2024-07-14 23:27:57 · 1043 阅读 · 0 评论 -
【常见的C++11新特性(二)】可变模板参数、lambda表达式、包装器、bind
(即没有名字的函数)。原创 2024-07-14 00:20:37 · 650 阅读 · 1 评论 -
【常见的c++11新特性(一)】右值引用和移动构造
c++11,即2011年发布的新c++标准。相比于c++98和03,c++11带来了很多变化,其中包含了约140多个新特性,以及对c++03标准中大约600多个缺陷的修正。这使得c++11更像是一个从c++98/03孕育出来的一个新版本。对比于之前的版本,c++11能更好的用于系统开发和库开发、语法更加的泛华和简单化、更加稳定和安全,不仅功能更加强大,而且能提升程序员的开发效率。这也是我们学习c++11的重要原因。下面介绍常见的一些c++11特性。左值引用只能引用左值,不能引用右值,比如。原创 2024-06-10 17:00:26 · 1678 阅读 · 6 评论 -
【数据结构】哈希表的原理及其实现
哈希表类主要有两个模块需要实现,一个是节点类,还有一个是存储节点的容器。跟线性探测代码不一样的地方在于,拉链法的节点实际上是一个链表的头节点(桶)。值得注意的是,由于线性探测法的特性,删除一个元素之后可能会影响后续查找元素。造成哈希冲突的主要原因是,哈希表的大小是有限的,而输入的数据可能会非常多,因此不可能避免出现哈希冲突。于是,当我们发生哈希冲突时,不用去哈希表中找空位了,因为当前桶是一个单链表,插入元素时直接头插就好了。该文件封装实现了一个哈希表类,哈希函数是除留余数,解决哈希冲突的方法采用拉链法。原创 2024-05-26 16:02:15 · 1119 阅读 · 1 评论 -
【数据结构】红黑树的原理及其实现
与AVL实现类似,红黑树的节点依旧有三个指针分别指向父节点、左孩子节点、右孩子节点。且有一个变量表示当前节点的颜色。初始默认是红色。为什么默认设置为红色呢?这是因为插入节点时,新节点一定与空叶子节点相邻。而根据红黑树的性质,空叶子节点的颜色是黑色,这就使得,如果新插入节点是黑色,那么每插入一次这条路径就一定会多出来一个黑色节点,即一定要调整。虽然新节点是红色也可能会需要调整,但影响会少很多。//键值对//颜色:_kv(kv),_col(RED)原创 2024-05-15 12:43:37 · 869 阅读 · 1 评论 -
AVL树的原理及其实现
回顾我们对于二叉搜索树的了解,二叉搜索树的效率跟树的高度成反比。而且,数据插入的随机性导致普通的二叉搜索树甚至可能退化成一条“单链表”,这样的结构查找起来时间复杂度直奔O(N),这无疑是我们不想看到的。我们希望,无论数据怎么插入,二叉搜索树的结构都应该保持平衡,即看起来更加接近于完全二叉树或者满二叉树AVL树因此诞生。原创 2024-05-10 13:49:05 · 1238 阅读 · 15 评论 -
【STL】map和set的原理及其使用
在c++文档中是这么定义setset是按照一定次序存储元素的容器,其中控制比较逻辑,默认是小于。可以是一个仿函数,也可以是一个函数指针。set中的key必须是唯一的。不能修改key但是可以删除或者插入一个key。在内部,set中的元素总是按照其内部比较对象(类型比较)所指定的特定严格强弱排序准则进行排序。set访问元素的平均时间复杂度为O(logn).set的底层是通过二叉搜索树(红黑树)来实现的。原创 2024-05-04 19:54:55 · 975 阅读 · 2 评论 -
【数据结构】二叉搜索树的原理及其实现
越低意味着整棵树越像完全二叉树,查找的效率也就越高。越高意味着越像单支树,查找的效率也就越低。为了保持二叉搜索树的性能,也就衍生出了AVL树和红黑树。无论是插入操作还是查找操作的时间复杂度都取决于查找的时间效率,也就意味着,查找的效率极大程度上体现一颗二叉搜索树的性能。我们很容易想到,对二叉搜索树进行中序遍历就可以得到一个节点值递增的序列。二叉搜索树的应用其实非常广泛,像我们经常用的map,set等容器,底层其实就是一个二叉搜索树。根据二叉搜索树的性质,左节点的值 < 根节点的值 < 右节点的值。原创 2024-04-26 10:37:15 · 1130 阅读 · 2 评论 -
【多态】初次遇见我就爱上了多态
表面上来看,虚函数就是被关键字virtual修饰的函数。而一旦被声明成了虚函数,将来通过父类指针或者引用就能区分出应该调用父类的函数还子类的函数。虚函数不能被static修饰,也通常不能同时是内联函数。要想区分两个函数是重写,重载还是重定义,首先观察其函数名是否一样。如果不一样,那就直接拜拜。再观察两个函数是否在不同的域中。如果在同一个域中且返回值类型不同,那就构成重载。如果一个在子类,一个在父类,那么再观察这俩函数是否是虚函数。原创 2024-04-23 21:52:59 · 2066 阅读 · 2 评论 -
【继承】菱形继承以及虚拟菱形继承
虚拟继承中的虚拟基类成员只会实例化一份,在菱形继承中解决了数据冗余的问题,同时也解决了二义性。虚拟继承虽然解决了菱形继承问题,但它也引入了额外的复杂性和性能开销。每次通过派生类访问虚拟基类的成员时,都需要进行额外的间接寻址。这可能会影响性能,尤其是在性能敏感的应用中。因此,在设计类的继承结构时,应仔细考虑是否真的需要虚拟继承。在选择是使用继承还是组合时,我们应该根据实际需求的上下文来决定。如果类之间的关系是很明显的is a且又要实现多态的时候,用继承比较合适。原创 2024-04-18 11:54:27 · 945 阅读 · 0 评论 -
【继承】初步了解C++继承
派生访问说明符(继承方式)对于派生类的成员(及友元)能否访问其直接基类的成员没什么影响,在派生类的内部都能访问基类的protected、public成员,但不能访问private成员。虽然基类的private成员无论如何都不能被派生类直接访问,但是还是会被继承过来。基类可以提供非private的接口给让派生类间接访问。如果基类只想让成员在派生类内部访问,而不想被派生类实例化后的对象直接访问,可以将其的访问限定符设为protected。protected是因为继承才出现的。原创 2024-04-16 23:31:00 · 1155 阅读 · 0 评论 -
【STL】priority_queue的底层原理及其实现
解释以上内容(优先级队列)跟stack、queue一样,都是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大或者最小的(默认最大.优先队列的底层数据结构是用堆来实现的。作为容器适配器,priority_queue默认是由vector类来实现的。优先队列(堆)这种数据结构需要快速随机访问元素的能力。除了vector,deque类也可以用来作为优先队列的底层容器。严格来说,只要满足以下能力的容器都可以作为优先队列的底层容器:(1)empty():检测容器是否为空。原创 2024-04-10 18:22:06 · 1366 阅读 · 2 评论 -
【STL】stack与queue的底层原理及其实现
(图片来自知乎)1.stack是一种容器适配器,模拟了栈的数据结构。数据只能从一端进去,另一端出来(先进后出2.stack适配器默认是由deque容器实现的,也可以显示要求stack的底层封装的容器类型。由于栈的特性,array和不能用来构造stack适配器。3.stack的底层容器必须需要支持以下几个操作:(1)empty:判空操作(2)back:获取尾部元素操作(3)push_back:尾部插入元素操作(4)pop_back:尾部删除元素操作。原创 2024-04-09 20:35:52 · 1172 阅读 · 2 评论 -
initializer_list初始化列表
使用些容器时我们经常会用列表初始化:为什么我们可以用这种{}的方式初始化容器类对象呢?原创 2024-04-09 17:30:05 · 257 阅读 · 0 评论 -
【STL】顺序容器与容器适配器
顺序容器类型作用vector可变大小的数组,支持快速访问,除尾元素的插入或者删除很慢string与vector相似,只不过专门用来存字符list双向链表。只能双向顺序访问,插入删除的效率都很高单向链表。只能单向顺序访问,插入删除的效率都很高deque双端队列。支持快速随机访问。在头尾位置插入删除很快,中间则很慢array固定大小的数组。支持快速随机访问。不能删除和添加元素每一个适配器都应该要有两个构造函数:默认构造创建一个空对象。接受一个容器的构造函数拷贝该容器来初始化适配器。原创 2024-04-09 15:38:52 · 899 阅读 · 15 评论 -
【STL】list的底层原理及其实现
list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是用双向链表实现的(线性),每个元素都存在相互独立的节点中,每个节点都有一个指针分别指向前一个节点和后一个节点。因为底层结构是链表,list的插入和删除操作是非常高效的,这与vector容器相反。但是由于链表的结构特点,list的各个节点之间的物理地址是不连续的,也就导致了任意访问某个节点的效率较低。list的空间消耗会比vector大。原创 2024-04-07 17:29:31 · 1335 阅读 · 1 评论 -
【STL】vector的底层原理及其实现
vector一共有4个构造函数,分别对应不同的构造场景。1.vector().无参构造2..构造并且初始化n个元素的值为value.3..拷贝构造4..迭代器初始化构造int main()// 无参构造// 构造的同时初始化4个元素都为100// 迭代器初始化构造// 拷贝构造//迭代器初始化构造示例it!原创 2024-04-05 13:29:47 · 1258 阅读 · 0 评论 -
C++模板的原理及使用
泛型:是一种在编程语言中用于创建可重用代码的机制。它允许我们定义类、接口和方法,可以使用不同类型的参数进行操作,从而提高代码的灵活性和复用性。如果我们想实现一个Swap函数,就需要考虑所有被交换变量的类型(double、int、char等)。我们可以很容易的观察到,以上三个函数只是参数的类型不一样,函数体中的代码是一样的。虽然可以通过函数重载来区分不同参数但函数名相同的函数,但对于这种函数体代码一致的函数,重载函数重复定义完全一样的函数体,无疑使代码过于冗长,且不方便维护。原创 2024-03-18 18:27:30 · 1008 阅读 · 7 评论 -
流是什么?什么叫重定向?
通常我们会将重载> 运算符(overloaded)以用于输入/输出流操作,也就是说,我们之所以能用cout输出输入就是因为重载了运算符。我们知道C++的cout、cin是通过标准库提供的 头文件中的输入输出流类实现的。C++中把数据之间的传输操作称为流,流既可以表示数据从内存传送到某个载体或设备中,即输出流,也可以表示数据从某个载体或设备传送到内存缓冲区变量中,即输入流。,提供了输入/输出操作,如">>“和”原创 2024-03-18 16:12:09 · 1093 阅读 · 23 评论 -
模拟实现string类--重载输入输出流
声明了一个空间域用来声明string类,这是为了避免和std标准命名空间里的string冲突。原创 2024-03-15 21:43:36 · 483 阅读 · 2 评论 -
【内存分布管理】new与malloc以及delede与delete[]的区别
delete与delete[]的效果是不一样的,delete只会调用一次析构函数,而delete[]会调用多次。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误失去了对该段内存的控制,因而造成了内存的浪费。指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。因为对于内置类型,在new分配内存的时候就已经确定了内存的大小,并且记录了下来, 系统可以记忆并且进行管理,在析构时,系统并。原创 2024-03-14 13:34:37 · 992 阅读 · 0 评论 -
如何在vs上提交代码到gitee/github?
使用vs提交代码到gitee/github仓库原创 2024-03-11 21:56:20 · 731 阅读 · 2 评论 -
类与对象(三)--内部类、匿名对象
🔎 将内部类B看成是外部类A的一个友元类,相互独立,内部类无论变量有多少都不会影响外部类,对于外部类来说也同样如此。,对于A类来说,B类定义在它的类体里面,所以B类就是A类的内部类,相反,对于B类来说,A类是B类的外部类。🔎如果一个类定义在另一个类的内部,这个类就叫做内部类。内部类是一个独立的类,它不属于外部类,更。内部类可以轻松访问其外部类的私有成员。,通过一个类内部包含多个内部类,每个内部类分别实现一个接口或继承一个抽象类。: 如果一个类只在一个地方使用,可以考虑将其作为外部类的内部类,以。原创 2024-03-11 14:02:03 · 777 阅读 · 8 评论 -
类与对象(三)--static成员、友元
在c++中,友元(Friend)是一种机制允许一个类或函数访问另一个类的私有成员。通过使用友元关键字,可以将某个函数或类声明为另一个类的友元,从而赋予它对该类私有成员的访问权限。原创 2024-03-08 19:15:59 · 857 阅读 · 10 评论 -
拒绝隐式转换--explicit关键字
以上代码同时也说明了,构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有。以上代码的Test()函数中,可以直接给对象d1赋值一个2023,编译器。关键字可以避免一些潜在的错误,尤其是在涉及单参数构造函数的情况下,这主要用于防止在某些上下文中发生不期望的类型转换。现在将上面代码的构造函数用explicit关键字修饰。)生成一个没有名字的对象,再将这个对象。explicit关键字引入✒️。是一个关键字,同时也是。原创 2024-03-08 17:20:57 · 464 阅读 · 4 评论 -
类与对象(三)--构造函数体中的赋值和初始化列表的区别
在实践中,推荐使用初始化列表,特别是对于非静态常量成员、引用成员或具有自定义构造函数的成员。这样可以确保在进入构造函数体之前,所有成员都得到了正确的初始化。原创 2024-03-06 21:09:14 · 1022 阅读 · 4 评论 -
类模块的练习--实现日期类
🔎在前面对类的学习中我们已经初步的了解和使用类,现在我们可以尝试独立的实现一个日期类,包括日期类的运算符号重载。原创 2024-03-06 17:27:56 · 848 阅读 · 0 评论 -
类与对象(二)--类的六个默认成员函数超详细讲解
浅拷贝简单快速,但容易引发潜在的问题,特别是当对象包含动态分配的资源时。深拷贝较为安全,但由于需要额外的内存分配和复制操作,可能效率较低。在实现深拷贝时需要小心管理资源,防止内存泄漏等问题。原创 2024-03-05 22:02:32 · 1357 阅读 · 12 评论 -
类与对象(一)
我们知道,c语言是一门面向过程的语言,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。而c++、Java则是一个面向对象的语言,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完 成。面向过程"和"面向对象"是两种不同的编程范式,它们反映了程序设计和组织代码的不同思想。面向过程思想:面向过程编程的核心思想是将问题划分为一系列的步骤,每个步骤都是一个函数或者是一个子过程。程序的执行按照一些特定的步骤依次进行。面向对象思想:面向对象编程的核心是将程序看作是对象的集合。原创 2024-03-03 01:35:18 · 887 阅读 · 6 评论 -
利用缓冲区模拟进度条加载
用来定义ProcBar函数,该函数就是实现进度条的主核心代码,用“#”表示进度,利用之前学过的缓冲区知识,使用\r回车符来不断覆盖之前的“进度”。main函数的定义,以及download函数的定义,download函数模拟了在网络中下载文件的情景。声明各种头文件,以及ProcBar函数的声明,为了提高代码的灵活性,使用一个回调函数作为调用模拟进度条函数的参数。以下就是进度条的样子咯,感兴趣的朋友可以自己去“美化”一下hh。界面呢非常简洁,代码也非常简单,非常适合有用来练手或者消遣。原创 2024-02-26 00:13:41 · 430 阅读 · 0 评论 -
详细讲解缓冲区
表示的是换行,可是,实际上这里的换行有两个动作:回车+换行。通过在内存中存储临时数据,程序可以利用缓冲区进行高效的读写操作,而不必每次都直接访问慢速的外部存储设备。缓冲区(Buffer)是计算机科学中常见的概念,它是一块内存区域,用于存储临时数据。,还没来得及从缓冲区输出到显示文件上,就执行sleep函数休眠了,这也是要等3秒才会打印出hello字符。这三个流其实就是三个文件的指针,可以实现基本的用户交互。例如,通过在网络通信中使用缓冲区,可以将大块的数据分割成小块,减少网络传输的延迟,提高效率。原创 2024-02-24 22:20:51 · 1005 阅读 · 1 评论 -
NULL和nullptr到底是什么?它们的区别又是什么?
为了保持良好的编程习惯,我们在声明某个变量时都应该给这个变量合适的初始值,不然容易出现不可预知的错误。对于指针来说更是如此,在c语言中我们就通常将暂时没有指向的指针置为NULL.原创 2024-02-15 21:17:40 · 1112 阅读 · 1 评论 -
auto关键字详讲
在上面的例子中我们可以看到,auto关键字提高了C++代码的可读性和灵活性,同时减少开发者在类型声明上的冗余,但是在早期c/c++中的auto含义是指自动存储器的局部变量,其作用过于狭隘,导致少有人使用。// 推导为int// 推导为double// 推导为const char*// num的类型为int,自动推导//auto推导出a+b的值是int类型4.结合模板:auto并不是万能的,对于复杂的表达式,可能会导致类型推导不准确,因此需要慎重使用。// 慎重使用,确保类型推导准确。原创 2024-02-15 20:12:24 · 1093 阅读 · 2 评论 -
你了解内联函数吗?
分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到(只在当前文件内生效).面试题宏的优缺点:优点:1.增强代码的复用性。2.原创 2024-02-10 20:09:19 · 980 阅读 · 1 评论 -
你了解引用和指针的区别吗?
在计算机编程中,引用和指针是两个重要的概念,它们用于处理内存中的数据。它们在很多编程语言中都有相应的支持,例如C++和C。对于c语言来说,指针是最重要的概念之一,想要学好c语言就难以绕开对于指针的学习。那么对于c++来说,引用这一概念也同样如此。C语言内功修炼---指针详讲(初阶)-CSDN博客C语言内功修炼--指针详讲(进阶)-CSDN博客。原创 2024-02-05 21:09:09 · 944 阅读 · 5 评论 -
函数重载你真的了解吗?
在C语言中,函数名修饰是相对较简单的,因为C语言本身不支持函数的重载。因此,C语言的函数名在源代码中的写法和编译后的二进制代码中是一样的。值得注意的是,如果仅仅是函数返回值不同是无法构成函数重载的。具体而言,函数重载允许你定义同名的函数,但这些函数应该有不同的参数类型、参数个数或者参数顺序。可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标。文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。(老师要带同学们回顾一下)原创 2024-02-02 23:00:06 · 2762 阅读 · 1 评论 -
c++的发展史、缺省参数、命名空间你了解吗?
定义命名空间,需要使用到namespace关键字 ,后面加命名空间的名字,然后用一对{}括起来。{}中所有的变量或者函数都是该命名空间的成员。// 命名空间中可以定义变量/函数/类型//注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中int val;我们可以看到,虽然s1和s2命名空间里面都有一个A(int,int)函数,但是各自实现的功能不一样,在s1命名空间里实现两数相加,在s2命名空间里面实现两数相乘。原创 2024-01-30 22:45:41 · 1023 阅读 · 3 评论