自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(46)
  • 收藏
  • 关注

原创 Linux中dup和dup2函数

到目前为止,文件描述符和打开的文件之间似乎呈现出一一对应的关系。然而,实际并 非如此。多个文件描述符可以指向同一打开文件。这些文件描述符可在相同或不同的进程中打开。

2024-12-26 22:34:44 794

原创 Linux中的lseek 函数与fcntl函数

文件打开时,会将文件偏移量设置为指向文件开始(使用O_APPEND除外),以后每次read()和write()会自动对其调整,以指向已读或已写数据的下一字节。文件偏移量通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数(下一个read()或write()操作的文件起始位置)。文件的第一个字节的偏移量为0。对打开的文件描述符进行控制,如获取或修改打开文件的状态标志(对应open函数的flags参数)2)SEEK_CUR:文件偏移量设置为当前文件偏移量加上offset,offset可以为负数。

2024-12-25 20:16:32 1150

原创 基础排序算法

这里的n是待排序元素的个数,k是待排序序列中元素值的范围(最大值与最小值的差加1)。计数排序的空间复杂度:O(n + k)。最好情况时间复杂度:O(n + k)最坏情况时间复杂度:O(n + k)选择排序的空间复杂度:O(1)。冒泡排序的空间复杂度:O(1)。插入排序的空间复杂度:O(1)。1. 最好情况:O(n^2)2.最坏情况:O(n^2)。2.最坏情况:O(n^2)1.最好情况:O(n)最坏情况:O(n^2)

2024-12-23 20:29:12 848

原创 C++ 中面向对象编程中对象的状态存储与恢复的处理

这种方式可以根据程序运行时的需求灵活分配内存,但需要手动使用 delete 来释放内存,避免内存泄漏。2)反序列化:是从存储或传输的格式中恢复对象状态。2)移动:C++11引入了移动语义,通过移动构造函数和移动赋值运算符来高效地转移资源的所有权。栈存储的对象生命周期由其所在的作用域决定,作用域结束时对象自动销毁,不需要手动释放内存。1)序列化:是将对象的状态转换为可以存储或传输的格式,比如转换为字节流。当进入包含对象定义的代码块时,对象被创建并压入栈中。1)复制:可以通过定义拷贝构造函数来复制对象。

2024-12-21 19:51:37 746 1

原创 二叉树的遍历

如果cur的左子树不为空,将cur的左子节点压入 stk 中。3、上面循环停止后,弹出栈顶节点,记录为 node,打印 node,并且让 cur=node->right;3、第三步看这个 node 有没有左孩子,如果有左孩子把左孩子放入到队列中,如果node 有右孩子,把右孩子放入到队列中。2、先把 cur 节点压入栈中,对以 cur 节点为根节点的整棵子树,依次把整棵树的左边界压入到栈中,即不断的执。2、从s1中弹出的结点记为cur,然后将cur的左子树压入到s1中,然后把cur的右子树压入到s1中。

2024-12-19 21:57:45 468

原创 C++中的二叉树

二叉树是每个节点最多有两个子树的树结构。

2024-12-18 17:01:42 334

原创 优先级队列

push() 加入一个元素,添加元素后自动将优先级队列维护成最大堆结构。pop() 删除堆顶元素,删除之后自动将优先级队列维护成最大堆结构。优先级队列就是堆结构,堆结构就是完全二叉树结构。size() 返回优先队列中拥有的元素的个数。top() 返回优先队列中有最高优先级的元素。empty() 如果优先队列为空,则返回真。

2024-12-14 17:04:00 487

原创 智能指针中的unique_ptr(独占智能指针)

删除了拷贝构造和赋值运算符。

2024-12-11 20:37:46 334

原创 智能指针中的weak_ptr(弱引用智能指针)

弱引用智能指针 std::weak_ptr 可以看做是shared_ptr的助手,它不管理 shared_ptr 内部的指针。std::weak_ptr 没有重载操作符*和->,因为它不共享指针,不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视shared_ptr 中管理的资源是否存在.

2024-12-10 21:30:35 1216

原创 智能指针中的share_ptr(共享智能指针)

共享智能指针对象初始化完毕之后就指向了要管理的那块堆区内存,如果想要查看当前有多少个智能指针同时管理着这块内存可以使用共享智能指针提供的一个成员函数use_count。

2024-12-09 22:25:59 920

原创 C++中的纯虚函数和抽象类

抽象类:有纯虚函数的类叫做抽象类(纯虚类),抽象类不能创建对象,如果子类没有重写父类的纯虚函数,那么子类也是抽象类,抽象类,一般作为基类,虚函数在虚表中存放的是函数地址,纯虚函数在虚表中存放的是 0(虚表指针在我发的C++中的多态性中有介绍)析构函数在继承关系中,编译器会将子类和父类的析构函数名字改为一样的,造成函数隐藏,下面代码的a是A类型的,所以会调用父类的析构函数,子类的不会调用。让父类的析构函数是虚函数,这样就发生重写,这样调用的析构是子类的析构,会在子类的析构函数里面去调用父类的析构。

2024-12-08 15:02:10 747

原创 C++中的多态性

只要类中有虚函数,那么类中就会多一个成员变量,这个成员变量就是虚函数表的指针,调用虚函数,先访问这个对象里的虚函数表指针,通过虚函数表指针找到虚函数那个数组,在遍历数组找到虚函数地址。多态的基础: 需要有重写,子类重写父类的 返回值 名字 参数相同的虚函数,(只要父类的函数是虚函数即可)。重写的函数和被重写的函数必须都为virtual函数,并分别位于基类和派生类中,如果父类被重写的函数加了。每个包含了虚函数的类都包含一个虚函数表(存放虚函数指针的数组,就是存放的是虚函数的地址),调用虚函。

2024-12-07 22:44:29 928

原创 C++中的继承性

定义:继承性是面向对象编程的重要特性,它允许一个类(子类或派生类)继承另一个类(父类或基类)的成员变量和成员函数,以实现代码复用和层次化设计,有公有、保护和私有继承三种方式。当父类和子类中有同名函数时,子类中的函数会将父类中的同名函数隐藏(函数隐藏)父类对象不可以访问子类对象中的成员变量,因为创建父类对象不会创建子类对象。两个派生类继承同一个基类,又有某一个类同时继承这两个派生类。菱形继承会使子类继承两份相同的数据,导致资源浪费。如果此时想通过子类对象访问父类对象,需要作用域。继承同名成员处理方式。

2024-12-06 21:22:17 924

原创 C++中的封装性

如果之后想要提高 getArea 函数计算圆面积的精度,例如使用更精确的 π 值,只需要修改 getArea 函数内部的实现,而使用 Circle 类的外部代码不需要进行任何改变。将数据成员设为私有(private),可以防止外部代码直接访问和修改对象的内部数据,从而保证数据的完整性和安全性。(将事物的属性(成员变量)和行为(成员函数)封装在一起形成一个类,并且设置相应的访问权限)当需要对类的内部实现进行修改时,只要接口(公有成员函数)不变,外部代码不需要进行修改。例如:设计一个圆类,求圆的周长。

2024-12-05 20:25:39 810

原创 c/c++中的静态链接与动态链接

动态链接是指在程序运行时才将外部共享库加载进内存并与程序进行链接的方式,它减小了可执行文件大小,方便更新库,但运行时需依赖库文件,部署相对复杂。静态链接是编译程序时把库文件中的代码和数据复制到可执行文件中的链接方式,程序运行时不依赖外部库,方便移植,但文件较大,更新库需重新编译程序。- 动态链接:只需更新动态库,使用该库的所有程序无需重新编译就能使用新的功能,更新更方便。2. 便于更新:只需更新动态库,使用该库的所有程序无需重新编译就能使用新的功能。- 静态链接:在编译时就完成链接,不具备运行时的灵活性。

2024-12-04 17:45:05 847

原创 C++中对象的初始化和清理

5.当已经提供了有参构造时,程序不会提供无参构造(若此时调用无参构造,程序报错,须程序员手动提供无参构造)构造函数:主要作用在于创造对时为对象的成员属性(成员变量)赋值,构造函数由编译器自动调用,无需手动调用。2.如果用户定义了拷贝构造,C++不再提供其他的任何构造函数(无参、有参、默认拷贝构造)1.如果用户定义有参构造,C++不再提供默认的无参构造,但会提供默认的拷贝构造。4.程序在调用对象的时候会自动调用构造函数,无需手动调用,而且只会调用一次。1.默认构造函数(无参,函数体为空)

2024-12-02 18:54:35 906

原创 auto与decltype

原则上将,exp只是一个普通的表达式,它可以是任意复杂的形式,但必须保证exp的结果是有类型的,不能是void;在C++中, auto 是一个类型说明符,它让编译器在编译阶段自动推导变量的类型,其类型取决于初始化表达式的类型。2)auto要求变量必须初始化,这是因为auto根据变量的初始值来推导变量类型的,如果不初始化,变量的类型也就无法推导而decltype不要求。auto* a 加一个 * 是在强调变量 a 是指针,故a只能接受指针类型,并不是将变量类型改为指针类型,没有指针auto类型。

2024-11-29 22:52:59 598

原创 C++中的volatile关键字

每次检查时,都会从内存读取 flag 的最新值。这是因为编译器通常会对代码进行优化,例如把变量的值缓存到寄存器中,但对于 volatile 变量,每次访问都要从内存中读取,以确保获取到最新的值。因为 flag 是 volatile ,编译器不会对 while 循环中 flag 的读取进行优化,会确保每次都从内存读取最新的值,这在多线程或硬件交互的场景下很重要。它主要用于告诉编译器这个变量的值是固定的,编译器可以利用这一点进行一些优化,例如将变量的值替换到使用它的地方,而不用每次从内存读取。

2024-11-28 21:41:24 708

原创 C++中类型别名和using声明

定义: using 声明是C++11引入的一种定义类型别名的方式,它的功能类似于 typedef ,但在某些复杂类型的定义上更加直观。使用方法:在模板编程中,可以用 using 声明来定义别名。定义:类型别名是为已存在的数据类型定义一个新的名字。在模板编程和定义复杂的类型别名(如嵌套类型别名)时更方便。使用方法:使用 typedef 关键字,后面接原数据类型,再跟新的类型别名。使用方法:使用 using 关键字,格式为 using 别名 = 原数据类型。类型别名(typedef)的使用方法。

2024-11-27 15:02:20 945

原创 C++中的多继承和虚继承

在这个例子中,涉及虚继承和虚函数重写。如果虚函数表处理不当,可能会导致程序在运行时调用错误的函数,而且由于虚继承和虚函数机制本身比较复杂,编译器在编译过程中也需要更多的时间来检查和处理相关的逻辑,增加了出错的风险。在这个例子中, GraphicalObject 类通过多继承拥有了 Shape 类设置尺寸和 Color 类设置颜色的功能,能够方便地将不同的功能组合在一起,用于表示具有形状和颜色属性的图形对象。例如,有基类A和基类B,类C可以同时继承A和B,这样C就拥有了A和B中的成员变量和成员函数。

2024-11-26 22:27:25 1108

原创 C++中的Lambda表达式

1)[capture list] 是捕获列表,用于指定lambda表达式所在作用域中的变量如何被捕获(可以是值传递或者引用传递),例如 [&] 表示以引用方式捕获所有外部变量, [=] 表示以值的方式捕获所有外部变量。即使在调用lambda表达式后修改 num 的值,lambda表达式内部使用的 num 值依旧是捕获时的值(10)。这里lambda表达式按引用捕获 num ,在lambda表达式内部修改 num 的值,外部的 num 变量也会随之改变。可以指定部分变量按值捕获,部分变量按引用捕获。

2024-11-25 22:37:54 2494

原创 C++中的模板特化和偏特化

然后进行了偏特化,当 T1 为 int 类型时,新的 Pair 类有一个额外的成员函数 multiply ,用于计算 first 和 second 的乘积。然后针对 bool 类型进行了完全特化,在完全特化的类中可以提供与通用模板不同的实现,比如更高效的存储方式或者特殊的操作方法,以适应 bool 类型的特点。然后对 bool 类型且大小为10的栈进行了完全特化,在特化版本中重新定义了 push 和 pop 等成员函数的具体实现。这种偏特化可以针对特定类型组合进行特殊的处理,以满足不同的需求。

2024-11-23 21:48:21 1236

原创 C++中移动语义和拷贝语义的区别及智能指针

在 uniquePtrExample 函数里, unique_ptr 演示了对象所有权的独占性,通过 std::move 转移所有权后,原指针 p1 就不再拥有对象的控制权。特点:采用引用计数机制。多个 shared_ptr 可以指向同一个对象,当所有指向该对象的 shared_ptr 引用计数为0时,对象才会被销毁。2)unique_ptr:独占所指向的对象,同一时间只能有一个unique_ptr指向一个对象,对象的所有权可以转移,但不能共享。智能指针是C++中的类模板,用于自动管理动态分配的内存。

2024-11-22 21:46:36 856

原创 C++中的移动语义

在移动构造函数和移动赋值运算符完成资源转移后,需要将源对象( other )的相关资源指针置空(如 other.data = nullptr )或者重置相关属性(如 other.length = 0 ),以表明资源已经被转移,防止源对象的析构函数错误地释放已经转移的资源。由于这个临时对象是右值,在初始化 str 对象时,会调用移动构造函数,将 temp 对象中的字符串资源转移到 str 对象中,而不是进行资源复制,提高了效率。在C++中,右值引用是一种引用类型,用于绑定到右值。使用右值引用实现移动语义。

2024-11-21 19:46:29 2895

原创 C++中的初始化列表

如果不用初始化列表,而是在构造函数体内赋值,会先调用默认构造函数创建成员对象,然后再调用赋值运算符进行赋值。但对于复杂对象,特别是涉及到资源获取(如动态内存分配)的成员,列表初始化可以避免先默认构造再赋值的过程,效率更高。成员变量的初始化顺序是按照它们在类定义中出现的顺序,而不是初始化列表中的顺序。如果对象有默认构造函数,先调用默认构造函数进行初始化,之后在构造函数体内又进行赋值操作,可能会涉及额外的资源消耗和时间开销。3.初始化的顺序和成员变量的顺序一致,与初始化参数列表中的顺序无关。

2024-11-20 18:11:19 597

原创 C/C++中的const

如果是 const 在 * 之前,如 const int *p ,表示指针 p 所指向的内容是常量,不能通过 p 来修改它指向的内容,但 p 本身可以指向其他地址;如果 const 在 * 之后,如 int * const p ,则表示指针 p 本身是常量,不能再指向其他地址,但可以通过 p 修改它指向的内容;- 在类中, const 成员函数是一个重要的概念。4).如果两个函数名相同,参数相同,但是一个是常函数一个是非常函数,那么这两个函数为函数重载,非常对象优先调用非常函数,常对象只能调用常函数。

2024-11-19 21:46:48 2232

原创 C++中的友元

在实际编程中,比如有一个复杂的数据结构类,像二叉树的节点类 TreeNode ,它有私有成员存储节点数据和左右子节点指针。Renderer 需要访问 Shape 类中的私有数据(如形状的顶点坐标等)来进行渲染,把 Renderer 设为 Shape 的友元类,就能方便地完成渲染工作这种紧密的协作。如果类A是类B的友元类,那么类A的所有成员函数都可以访问类B的私有(private)和保护(protected)成员。如果类A是类B的友元,不意味着类B是类A的友元。作用:让一个函数或类访问另一个类中的私有成员。

2024-11-18 19:06:29 507

原创 C++中的内联函数

普通函数:在程序执行到函数调用语句时,会将控制权转移到被调用函数的入口地址,执行函数体中的代码。编译器在处理对内联函数的调用时,会尝试将函数体的代码直接插入到函数调用处,而不是像普通函数调用那样,进行跳转指令执行函数体代码后再返回。内联函数:编译器会尽量将内联函数的代码直接嵌入到函数调用点,就好像在调用处直接书写函数体的代码一样。比如,简单的数学运算函数(如加法、减法函数),将它们定义为内联函数可以提高程序效率。当在类的内部定义成员函数时,该函数默认是内联函数。在C++中,内联函数是一种特殊的函数。

2024-11-17 20:08:26 942

原创 C/C++中的类型转换方式

也能用于具有继承关系的类层次结构中,进行向上转型(将派生类指针或引用转换为基类指针或引用),这种转换相对安全,编译器会在编译时检查类型的兼容性。比如在类的继承关系中,将基类指针不恰当地转换为派生类指针(没有进行正确的动态类型检查),可能会导致访问不存在的成员变量或函数,因为实际对象可能并不是转换后的类型所期望的。例如,将一个很大的 long long 类型的值转换为 int 类型, int 类型可能无法容纳这个值,从而导致溢出,产生错误的结果。类型转换是将一种数据类型的变量转换为另一种数据类型的过程。

2024-11-16 21:36:04 1319

原创 Linux系统编程中的read 和 write函数

2.buf:缓冲区,要写入文件或设备的数据(读可以不用缓冲区,直接写需要写入的内容即可)3.count: buf 缓冲区存放的最大字节数。2.buf:读取的数据保存在缓冲区buf中。3. -1 :出错,并设置errno。1.>0: 读取到的字节数大小。错误:返回-1并设置errno。从打开的设备或文件中读取数据。(ssize_t就是int)向打开的设备或文件中写数据。2.=0 :文件读取完毕。成功:返回写入的字节数。1.fd:文件描述符。1.fd:文件描述符。

2024-11-14 21:02:55 633

原创 C++静态成员

1.静态成员函数只能访问静态成员变量(静态成员函数没有this指针,不能区分成员变量属于哪个对象,所以访问不了非静态成员变量)2.没有this指针,所以静态成员函数内部不能使用非静态成员变量和非静态成员函数(无法给非静态成员函数的隐含指针this传参)在C++中,类内的成员变量和成员函数分开储存,只有非静态成员变量才属于对象上。3.在类内声明,类外初始化(对象.静态成员变量,或者类::静态成员变量)静态成员 就是在成员变量或成员函数前加static,变成静态成员。静态成员分为静态成员变量和静态成员函数。

2024-11-13 22:28:33 844

原创 C++中的命名空间

命名空间是一个声明性区域,为其内部的标识符(类型、函数和变量等的名称)提供一个范围。命名空间之外的标识符可通过使用每个标识符的完全限定名(例如 std::vector)来访问成员,也可通过单个标识符的 using 声明 (using std::string) 或命名空间中所有标识符的 using 指令 (using namespace std;比如,将所有和文件操作相关的函数放在一个名为“file_util”的命名空间下,将网络相关的放在“network_util”命名空间下,方便代码的维护和理解。

2024-11-12 19:21:19 629

原创 C/C++中的预处理指令

例如 #define SQUARE(x) (x)(x) ,在代码中使用 SQUARE(5) 时,会在预处理阶段直接替换为 (5)(5) ,没有函数调用的开销,速度相对快。宏定义只是简单的文本替换,不会检查参数类型。还是上面的 SQUARE 宏,如果写成 SQUARE("abc") ,在预处理阶段也会替换成 ("abc")*("abc") ,这在语法上是错误的,但编译器在预处理阶段不会发现。#if、#ifdef、#ifndef、#else、#elif、#endif:这些指令用于根据条件决定是否编译某段代码。

2024-11-09 22:40:04 689

原创 函数模板与类模板

使用函数模板时,编译器会根据实际参数类型自动生成相应的函数实例。类模板允许定义一个类的模式,使得类中的某些数据成员、成员函数的参数和返回值类型能够是任意类型。上述例子中,编译器看到传入的是int类型的参数,会将T确定为int类型来生成相应的函数。以template开头,其中T是模板参数,表示函数的参数类型。类模板的定义以template开头,其中T是模板参数。如:定义一个泛型向量类,可以存储任意类型的元素。直接传入实参,编译器会自动推导出模板参数类型。类模板需要显式指定类型参数来实例化。

2024-11-08 18:28:09 397

原创 C++函数重载

C++编译器在编译函数的时候会在名字的基础上加上参数类型来识别不同的重载函数,但是,C语言函数被定义成什么,编译后仍然是原名,所以,C语言不能发生函数重载。2.函数重载碰到函数默认参数(会发生是歧义)3.函数形参类型、个数或者顺序不同。函数名可以相同,提高复用性。1.引用可以作为重载条件。1.在同一个作用域下。

2024-11-07 20:49:30 453

原创 new与malloc

为了避免这些问题,在使用 malloc 时,应该始终检查其返回值,并在分配失败时采取适当的错误处理措施,例如释放已分配的资源、输出错误信息并终止程序,或者尝试采取其他策略来减少内存使用。如果在一个复杂的程序中,malloc 失败后没有被正确处理,可能会导致部分数据无法正确存储,进而在后续的计算中产生错误的结果。malloc申请的空间要用free函数释放。new是操作符,利用new在堆区开辟数据,开辟的数据需要手动开辟,在使用结束后用delete手动释放,利用new创建的数据,会返回该数据对应的类型指针。

2024-11-06 18:21:06 746

原创 拷贝构造函数

1)浅拷贝:简单的赋值拷贝操作(this->n=other.n)当使用一个已经创建完毕的对象初始化一个新对象时会调用拷贝构造;2)深拷贝:在堆区重新申请空间,进行拷贝操作。1.以值传递的方式给函数传值;2.以值的方式返回局部变量。拷贝构造分为深拷贝和浅拷贝。

2024-11-05 20:30:53 366

原创 类的三大特性(封装、继承、多态)

重写的函数和被重写的函数必须都为virtual函数,并分别位于基类和派生类中,如果父类被重写的函数加了vritual,子类继承父类,那么子类重写的函数加不加vritual都是虚函数重写的函数和被重写的函数,返回值,函数名和函数参数必须完全一致;封装的目的是保护对象的内部状态,防止外部直接访问和修改对象的数据,确保数据的完整性和程序的安全性。继承促进了代码的复用和模块化,通过继承一个基类,子类可以继承基类(父类)的所有特性,同时还可以添加新的特性或者覆盖基类中的方法。例如:设计一个圆类,求圆的周长。

2024-11-04 21:00:21 1559

原创 结构体与联合体

(2)结构体中的每个成员都占用独立的内存空间,而联合体中的所有成员共享同一块内存空间。(4)结构体的内存占用大小等于所有成员的内存大小之和,而联合体的内存占用大小等于其最大成员的内存大小,因此,联合体在内存占用上通常比结构体更节省;(3)结构体的成员在内存中按照定义的顺序依次排列,而联合体的所有成员共享同一块内存空间,因此只有一个成员可以存储有效值;1)结构体的成员可以同时被访问和修改,而联合体的成员只能同时访问和修改一个成员。与结构体的定义相似,联合体允许在相同的内存位置存储不同的数据类型。

2024-11-03 20:02:41 431

原创 数组的定义及数组名的含义

2.数组初始化时,若大括号{ }内的元素个数小于定义的数组长度,则剩余数组元素默认使用 0 填充。2.数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};1.定义数组时,若未给定数组元素的初始值,则必须指定初始数组长度。3.数据类型 数组名[ ] = { 值1,值2 ...};1.数据类型 数组名[ 数组长度 ](只定义不初始化);2.sizeof(数组名)表示整个数组的大小。3.&数组名表示整个数组的地址。1.数组名代表首元素的地址。

2024-11-01 18:58:14 531

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除