- 博客(55)
- 收藏
- 关注
原创 数据库的三范式是什么?
其他字段依赖主键是指,其他每个字段都与主键完全相关,当确定主键的值时就能确定其他所有字段的值。每列的原子性,表中的每一个字段都是不可分割的,同一列中不能有多个值。第一范式是对关系模式的基本要求,不满足第一范式的数据库不是关系型数据库。第二范式是在第一范式的基础上,要求表中的每一条数据可以被唯一区分,通常使用主键实现,其他所有字段都完全依赖主键。完全依赖是指,联合主键时,其他字段不可以只依赖主键中的某个字段,必须依赖联合主键中的每一个字段。在第二范式的基础上,非主键字段必须直接依赖于主键,不能存在传递依赖。
2024-12-22 19:56:24
778
1
原创 插入排序 计数排序 包括 代码 时间复杂度 空间复杂度 稳定性 是否能对代码进行提升
时间复杂度(全部逆序):o(n2)时间复杂度(全部有序):o(n)时间复杂度:o(n2)
2024-12-22 19:53:52
273
原创 对 MYSQL 架构的了解
缓冲池会根据一定的算法(如 LRU,最近最少使用算法)来管理内存中的数据页,将经常访问的数据页保留在缓冲池中,将不经常访问的数据页淘汰出缓冲池。:MySQL 支持事务处理,执行器在处理事务相关的 SQL 语句(如 BEGIN、COMMIT、ROLLBACK 等)时,会负责协调事务的开始、提交和回滚操作。例如,在一个银行转账事务中,如果转账操作失败,执行器会根据事务的回滚机制,将数据恢复到转账之前的状态。聚簇索引的叶子节点存储了实际的数据行,而非聚簇索引的叶子节点存储的是指向聚簇索引的指针。
2024-12-21 15:32:21
556
原创 选择排序、冒泡排序 包括 代码 时间复杂度 空间复杂度 稳定性 是否能对代码进行提升
假设我们现在排序ar[]={1,2,3,4,5,6,7,8,10,9}这组数据,按照上面的排序方式,第一趟排序后将10和9交换已经有序,接下来的8趟排序就是多余的,什么也没做。所以我们可以在交换的地方加一个标记,如果那一趟排序没有交换元素,说明这组数据已经有序,不用再继续下去。最坏时间复杂度(逆序情况):o(n2)时间复杂度(有序情况):o(n)时间复杂度:o(n2)空间复杂度:o(1)
2024-12-21 15:31:02
131
原创 C++ 中面向对象编程如何处理对象的状态存储与恢复?
对象状态存储是指将对象当前的成员变量值保存起来,而对象状态恢复则是指将之前保存的成员变量值重新赋值给对象,使对象回到之前的某个状态。当需要恢复对象状态时,从数据库中查询记录,并根据记录中的数据重新构建对象状态。概念:序列化是将对象的状态转换为可以存储或传输的格式,通常是字节流。它可以用于将一个对象的状态复制到另一个对象,实现部分状态恢复。它也可以用于更新一个对象的状态,使其与另一个对象的状态相同。概念:反序列化是序列化的逆过程,它将存储或传输过来的格式(如字节流)转换回对象状态。使用文件存储对象状态。
2024-12-21 10:25:04
491
原创 c++中如何处理对象的创建与销毁的时机?
当包含它的类对象被销毁时,成员对象的析构函数会被调用,从而销毁成员对象。例如,在前面的Container类中,如果Container对象c被销毁,其成员对象member的析构函数会在Container的析构函数中被调用,以确保正确地清理成员对象所占用的资源。静态局部对象在程序结束时销毁,或者在包含它的动态链接库(DLL)被卸载时销毁(如果是在 DLL 中定义的静态局部对象)。静态局部对象:在函数内部定义的静态局部对象,在第一次执行到该对象定义语句时创建,并且只会创建一次。当函数执行结束,对象就会被销毁。
2024-12-21 10:22:14
369
原创 如何实现工厂模式?
ShapeColorFactory1和ShapeColorFactory2是具体的工厂子类,它们分别创建一组相关的产品(如Circle和Red,Rectangle和Blue)。这种模式的优点是实现简单,缺点是不符合开闭原则(对扩展开放,对修改封闭),如果要添加新的图形类型,需要修改工厂类的createShape方法。工厂方法模式是在简单工厂模式的基础上,将工厂类的创建方法抽象成抽象方法,由具体的工厂子类来实现。这样,当需要添加新的产品类型时,只需要添加新的工厂子类,而不需要修改现有的工厂类。
2024-12-19 18:25:01
981
原创 如何处理对象的状态变化?
这里radius被设为private,外部代码不能直接访问和修改它,只能通过setRadius和getRadius函数来进行操作,这样可以保证对象状态的改变是符合预期的,例如可以在setRadius函数中添加一些验证逻辑,防止设置不合理的半径值。(假设circle是Circle类的一个对象),就可以将圆的半径设置为5.0,从而改变了对象的状态。例如,假设有一个简单的Circle类,用来表示圆,它有一个成员变量radius(半径)来表示圆的大小,这可以看作是对象的一种状态。状态变化的通知机制(观察者模式)
2024-12-19 18:20:07
480
原创 如何实现对象的克隆?如何实现单例模式?
在这个例子中,Singleton类的构造函数是私有的,这样就防止了外部代码直接创建Singleton类的对象。在上面的MyString类中,自定义的拷贝构造函数会为新对象的buffer指针分配新的内存空间,并将原对象buffer中的内容复制过来,这样就避免了两个对象的buffer指针指向同一块内存的问题。时,obj2就是obj1的一个浅拷贝。对于简单的类(没有动态分配资源的类),可以通过默认的拷贝构造函数来实现浅拷贝。在 C++ 中,对象克隆是创建一个与现有对象具有相同状态的新对象的过程。
2024-12-18 15:32:02
791
原创 如何实现序列化和反序列化?如何处理对象的生命周期管理?
std::unique_ptr独占所指向的对象,不能复制(但可以移动),当std::unique_ptr超出作用域时,它所指向的对象会被自动销毁。栈对象是在函数内部定义的对象,它们的生命周期由所在的代码块决定。当程序执行进入对象定义的代码块时,对象被创建,当执行离开该代码块时,对象被销毁。当引用计数为 0 时,对象被销毁。在这个例子中,p对象通过new创建,在使用完后,必须通过delete来释放内存,否则会导致内存泄漏。(std::unique_ptr)以下是使用std::unique_ptr的示例。
2024-12-17 16:51:16
521
原创 如何实现接口继承与实现继承的区别?如何处理多态性与性能的平衡?
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,只提供了函数签名,其形式为virtual 返回类型 函数名(参数列表)=0;在这个例子中,通过shapePtr调用area函数时,需要通过虚函数表查找Rectangle类中area函数的地址,这个查找过程会消耗一定的时间。当基类中的函数不是纯虚函数时,派生类可以选择继承基类的函数实现,也可以重写(覆盖)它。但是,对于复杂的多态层次结构和频繁调用的虚函数,内联可能不会起到很好的效果,因为虚函数的多态性本质上还是需要运行时的动态分派。实现继承(非纯虚函数)
2024-12-15 15:54:08
476
原创 C++ 中面向对象编程如何实现数据隐藏?C++ 中面向对象编程如何处理异常?
在处理异常时,要注意资源的清理,比如动态分配的内存、打开的文件等。这样,即使在抛出异常的情况下,当对象超出作用域时,析构函数也会被调用,从而正确地清理资源。通常,成员函数会被声明为public,用于提供一个接口来访问或操作类的私有或受保护成员。这里BaseClass中的protectedData可以在DerivedClass中被访问,但不能被外部非派生类的代码直接访问。私有成员(private)当数据成员或成员函数被声明为private时,它们只能在类的内部被访问。抛出的异常需要被捕获才能进行适当的处理。
2024-12-13 16:16:27
704
原创 C++ 中多态性在实际项目中的应用场景有哪些?C++ 中面向对象编程如何实现数据隐藏?
每个图形都有自己的绘制方法,但是在处理图形集合进行绘制操作时,希望能够以统一的方式来调用它们的绘制函数。游戏引擎可以通过一个Character指针数组或容器来管理游戏中的所有角色,在游戏循环中统一调用它们的行为函数,方便更新角色状态,提高代码的复用性和可扩展性。在游戏中,不同的角色(如战士、法师、刺客等)有不同的行为,如攻击、移动、使用技能等。private成员变量和函数:将类的成员变量和函数声明为private,可以限制它们只能在类的内部被访问。一、C++ 中多态性在实际项目中的应用场景。
2024-12-12 15:04:56
654
原创 什么是运算符重载? 如何在 C++ 中进行运算符重载?运算符重载在面向对象编程中的好处是什么?
这种直观的表达方式符合人们对数学运算的习惯,使得代码的意图更加清晰,降低了理解代码的难度,从而提高了代码的可维护性。例如,我们重载了+和*运算符用于复数类Complex,那么在任何需要对复数进行加法和乘法的地方,都可以直接使用这些运算符,而不需要重新编写专门的函数来实现相同的操作。这减少了代码的冗余,提高了代码的复用性。例如,对于一个日期类Date,重载+运算符来实现日期的加法(如加上一定天数),用户在使用Date类对象时,不需要了解日期加法的具体实现细节,只需要使用+运算符即可。
2024-12-11 16:36:18
671
原创 什么是纯虚函数?什么是抽象类?纯虚函数和抽象类在面向对象编程中的意义是什么?
例如,如果要添加一个新的游戏角色类型 “刺客”,可以从Character抽象类派生一个Assassin类,并实现attack()和move()函数来定义刺客的攻击和移动方式。例如,在一个游戏开发中,可能有一个Character抽象类,它有纯虚函数attack()和move(),不同类型的角色(如战士、法师等)作为派生类来具体实现这些行为。在 C++ 中,纯虚函数是在基类中声明的虚函数,它在基类中没有定义具体的函数体,而是通过在函数声明的结尾加上 = 0来标识。抽象类不能被实例化,也就是不能创建该类的对象。
2024-12-08 15:38:34
525
原创 什么是多态性?C++中如何实现多态?多态性的好处是什么?
例如,在图形绘制系统中,如果要添加一种新的图形,如三角形,只需要从Shape类派生出Triangle类,并重写draw函数即可,而不需要修改处理图形绘制的主程序部分。在main函数中,通过基类指针Shape*来调用draw函数,实际调用的函数是根据指针所指向的对象类型(Circle或Square)来决定的,这是运行时多态。通过多态,可以方便地将不同的算法封装在不同的类中,并且可以在运行时根据需要动态地切换算法,这样可以使程序的设计更加灵活,能够更好地应对复杂多变的需求。C++ 中实现多态的方式。
2024-12-07 19:34:22
786
原创 什么是继承性?C++中如何实现继承? 继承的好处和注意事项有哪些?
像前面提到的交通工具的例子,不同类型的交通工具(汽车、自行车、飞机等)都有速度和移动的属性和行为,将这些放在Vehicle基类中,其他交通工具类继承后就不用再次定义这些基本的功能。在这个例子中,Derived类正确地重写了Base类的print函数,因为Base类中的print函数是虚函数,并且Derived类中的print函数签名和Base类中的相同,这样在使用多态性(通过基类指针或引用调用派生类对象的函数)时就可以正确地调用Derived类的print函数。继承会导致基类和派生类之间有一定的耦合性。
2024-12-06 16:32:51
1025
原创 静态链接的特点是什么?动态链接的特点是什么?
例如,一个 C++ 程序使用了动态的网络通信库,当该库更新了内部实现以提高性能或者修复安全漏洞时,只要库的接口(函数签名、类结构等)没有改变,程序就可以直接使用更新后的库,而不需要重新编译,这使得程序的维护和更新更加方便。如果这个静态库更新了算法,即使只是一个小的修改,也需要重新编译使用这个库的程序,这使得程序的维护和更新相对麻烦。例如,多个不同的 C++ 程序都使用了同一个标准 C 动态库,操作系统会将该动态库加载到内存中一次,这些程序可以共享这份内存中的库代码,从而节省了大量的内存空间。
2024-12-05 16:00:14
539
原创 什么是封装性?C++中如何实现封装? 封装性的好处是什么?
相比我们将数据(用域来实现)在程序中定义为公用的(public)我们将它们(fields)定义为私有的(private)在很多方面会更好。第二种方法我们用属性(property),使用属性不仅可以控制存取数据的合法性,同时也提供了“读写”、“只读”、“只写”灵活的操作方法。这样的操作是不允许的,因为balance是private的。protected成员可以在类的内部和派生类(继承这个类的类)中访问。封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。
2024-12-05 15:59:14
459
原创 什么是函数重载? 函数重载的实现原理是什么?
编译器通过函数的参数类型、参数个数、参数顺序来区分不同的重载函数,在编译过程中,编译器会根据调用函数的实参类型选择合适的重载函数进行调用。在同一个作用域内,函数名字相同,参数(个数,顺序,类型)不同,那么就是函数重载。赋值:给一个已经存在的变量一个值。初始化:一个变量刚定义就赋值。函数重载和返回值没关系。
2024-12-01 19:37:02
404
原创 在 C/C++ 中,volatile 关键字的作用是什么?volatile 关键字与 const 关键字有什么区别?
例如,编译器可能会认为一个变量在某个代码段中不会被外部因素改变,从而将该变量的值缓存起来,以提高程序的执行效率。例如,一个定时器的计数寄存器,它的值会随着时间的推移而自动改变。如果没有volatile关键字,一个线程可能会将变量的值缓存在寄存器中,而当另一个线程修改了这个变量的值时,第一个线程可能无法察觉到这个变化。对于const变量,编译器可以进行一些优化,比如将其值直接替换到使用它的地方,因为它的值是固定不变的。访问硬件寄存器,确保对寄存器的值的读取和写入是直接的,不会被编译器优化。
2024-11-28 15:20:10
441
原创 什么是 C++ 中的函数对象?它有什么特点? 数对象与普通函数有什么区别? 如何定义和使用函数对象?
例如,在使用std::sort函数时,如果要自定义比较规则,使用函数对象可以方便地通过模板参数传递比较规则的类型,而使用普通函数可能需要进行一些函数指针类型的转换。普通函数一般不具有自己的状态(除非使用全局变量等方式,但这会带来全局状态管理的复杂性),而函数对象可以通过成员变量保存状态。比如,可以定义一个基类函数对象,然后派生出多个具有不同功能的子类函数对象。由于函数对象是通过类的成员函数(重载()运算符)实现的,编译器在适当的时候可以对其进行内联优化,提高程序的执行效率。函数对象与普通函数的区别。
2024-11-27 16:33:29
578
原创 什么是 C++ 中的多继承?它有哪些优缺点?什么是虚继承?为什么要使用虚继承?
多继承会使类之间的关系变得复杂。例如,如果类 C 继承自类 A 和类 B,且 A 和 B 都有function成员,在类 C 中可以这样调用:A::function()或者B::function(),这增加了代码的复杂性和维护成本。例如,假设有类 A、类 B 和类 C,类 C 可以同时继承自类 A 和类 B,这就形成了多继承的关系。这意味着类 C 将继承类 A 和类 B 的所有非 - private 成员(包括成员变量和成员函数),类 C 的对象可以访问和使用从类 A 和类 B 继承来的这些成员。
2024-11-26 17:04:49
1982
原创 什么是 C++ 中的类型别名和 using 声明? 如何使用类型别名和 using 声明?
当在一个作用域中使用using声明引入一个名字时,如果该名字与当前作用域中已有的名字冲突,会导致编译错误。例如,在同一个作用域中有两个同名函数,一个是通过using声明引入的,另一个是本地定义的,就会产生冲突。类型别名(Type alias)允许我们为已存在的类型创建一个新的名称。using声明只是引入了特定的名字,而不是整个命名空间。如果想引入整个命名空间,可以使用using namespace,using声明主要用于将命名空间中的名字引入到当前作用域,使得可以直接使用该名字而不必加上命名空间前缀。
2024-11-24 16:48:28
421
原创 什么是 C++ 中的智能指针?有哪些类型的智能指针?
std::unique_ptr是一种独占式智能指针,它所管理的对象只能有一个unique_ptr与之关联。std::weak_ptr是一种弱引用智能指针,它主要用于解决std::shared_ptr可能出现的循环引用问题。weak_ptr不控制对象的生命周期,它只是对一个由shared_ptr管理的对象的弱引用。weak_ptr可以通过lock函数来获取一个指向相同对象的shared_ptr,如果对象已经被释放(引用计数为 0),则lock函数返回一个空的shared_ptr。
2024-11-22 18:58:42
576
原创 移动语义和拷贝语义有什么区别?
如果对象包含资源(如动态分配的内存、文件句柄等),拷贝语义通常需要对这些资源进行深度复制,以确保每个对象都有自己独立的资源副本。在这个例子中,vec2接管了vec1所管理的内存资源,vec1被置于一种有效但未定义的状态(通常是为空或处于一种可以安全析构的状态)。对于独占资源的对象(如智能指针),移动语义可以快速地将资源的所有权从一个对象传递给另一个对象,避免了资源的浪费和不必要的复制。例如,在函数返回一个包含大量资源的对象时,使用移动语义可以避免对这些资源进行复制,从而减少内存分配和数据复制的开销。
2024-11-22 18:56:51
416
原创 什么是 C++ 中的移动语义?它的作用是什么?右值引用是什么?如何使用右值引用实现移动语义?
例如,当你有一个类MyClass,它包含一个动态分配的资源(如数组),在进行对象拷贝时,需要将资源从一个对象复制到另一个对象。例如,在std::vector的push_back操作中,如果新元素是一个右值(如一个临时对象),vector可以通过移动语义直接获取该右值对象的资源,而不是进行拷贝。例如,在使用std::unique_ptr(独占式智能指针)时,移动语义允许轻松地在不同的unique_ptr对象之间转移资源的所有权,这对于动态内存管理和对象所有权的传递提供了更自然的方式。中,a是左值,5是右值。
2024-11-21 17:12:45
1104
原创 什么是 C++ 中的初始化列表?它的作用是什么?初始化列表和在构造函数体内赋值有什么区别?
在Rectangle类的构造函数中,通过初始化列表直接调用Point类的构造函数来初始化topLeft和bottomRight,而不是先默认构造Point对象,再通过赋值操作来设置坐标,这样可以提高效率,特别是当Point类的构造函数中有一些复杂的初始化操作时。当类中包含其他类对象作为成员变量时,如果这些成员变量所属的类有自己的构造函数,使用初始化列表可以直接调用合适的构造函数来初始化成员变量,避免先调用默认构造函数创建对象,再通过赋值操作来给成员变量赋值。初始化列表和在构造函数体内赋值有什么区别?
2024-11-20 16:17:41
834
原创 什么是 C++ 中的友元函数和友元类?友元的作用是什么?有什么注意事项?
比如,在一个图形绘制系统中,有一个Shape类和一个Renderer类,Renderer类需要访问Shape类的私有成员来正确地绘制形状,此时可以将Renderer类声明为Shape类的友元类。当两个类相互声明为友元时(即 A 类是 B 类的友元,同时 B 类也是 A 类的友元),可能会导致复杂的依赖关系。在这个例子中,Mechanic类是Car类的友元类,Mechanic类中的repairEngine函数可以访问Car类的私有成员engineStatus来修改汽车发动机的状态。坏处:破坏了类的封装性。
2024-11-18 16:28:09
1853
原创 什么是 C++ 内联函数?它的作用是什么?内联函数与普通函数有什么区别?如何定义和使用内联函数?
在普通函数调用时,会涉及到一系列的操作,如保存当前的执行上下文(包括程序计数器、寄存器等的值)、将参数压入栈中、跳转到函数的入口地址、执行函数体、将返回值存储到合适的位置、恢复之前保存的执行上下文等。如果将square函数定义为内联函数(inline int square(int x)),编译器可能会将函数体直接插入到循环内部的调用位置,这样就避免了频繁的函数调用开销,从而可能提高程序的执行速度。编译器在编译阶段会尝试将内联函数的代码直接嵌入到调用该函数的地方,就好像把函数体中的代码直接写在调用处一样。
2024-11-17 15:48:46
972
原创 C/C++ 中有哪些类型转换方式? 分别有什么区别?类型转换可能会带来哪些问题?
c风格的转换的格式很简单 (type)expression,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比如你可以把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成指向一个派生类对象的指针,这两种转换之间的差别是巨大的,但是传统的c语言风格的类型转换没有区分这些。当从`double`转换为`float`时,由于`float`的尾数部分较短,无法精确表示`double`中的所有有效数字,从而导致精度丢失。
2024-11-16 19:17:21
785
原创 什么是 C++ 中的常量表达式? 有什么用途?如何判断一个表达式是否是常量表达式?
,`c`是常量表达式,`2`是常量表达式,它们通过加法运算组合后的`d`也是常量表达式。- 如果一个函数或者变量被声明为`constexpr`,并且满足`constexpr`的要求(如`constexpr`函数的函数体只能包含返回语句等简单操作,`constexpr`变量必须用常量表达式初始化),那么它就是常量表达式。- 当一个表达式是由多个子表达式通过算术(`+`、`-`、`*`、`/`等)、逻辑(`&&`、`||`、`!`等)、位运算(`&`、`|`、`^`等)组合而成时,需要检查每个子表达式。
2024-11-15 16:00:54
899
原创 C++ 中的异常处理机制是怎样的?什么情况下应该使用异常处理?异常处理的优缺点是什么?
如果在计算参数的函数中出现错误(如参数超出范围),可以抛出异常,让绘制图形的函数或者更高层的函数来捕获并处理,而不是在每个函数中都返回错误码来层层传递错误信息。例如,在一个由多个模块组成的大型程序中,一个底层模块中的函数出现异常,这个异常可以很方便地传递到高层模块,使得高层模块能够根据情况进行处理,而不需要在每个函数调用中都手动传递错误码。例如,在一个复杂的对象构造过程中,可能已经分配了部分资源,当后面的内存分配出现问题时,通过异常处理可以在catch块中释放之前分配的资源,避免资源泄漏。
2024-11-13 16:21:27
1001
原创 什么是c++命名空间 有什么作用?如何定义使用命名空间?且交代命名空间是否允许嵌套?
例如,你可能使用了两个不同的库,它们都有一个名为print的函数。比如,你可以为图形处理相关的代码创建一个Graphics命名空间,为网络通信相关的代码创建一个Network命名空间。例如,你可以把一组相关的函数、类、变量等放在一个命名空间中。语法上,命名空间的定义使用关键字namespace,后面跟着命名空间的名字,再加上花括号{},在花括号内是属于这个命名空间的各种声明。using声明可以将命名空间中的特定实体引入到当前作用域,这样就可以直接使用实体名,而不需要使用命名空间限定符。
2024-11-12 18:50:21
590
原创 解释一下宏定义和函数调用的区别
例如,对于宏定义#define SQUARE(x) x * x,当调用SQUARE(2 + 3)时,预处理器会将其替换成2 + 3 * 2 + 3,这显然不符合预期的(2 + 3) * (2 + 3)运算顺序,正确的宏定义应该是#define SQUARE(x) ((x) * (x))。宏定义在调试时相对不太方便,因为宏是在预编译阶段就完成了替换,在调试工具中看到的代码往往是已经替换后的代码,很难直接追溯到宏定义本身的情况,而且对于带参数的宏,如果出现问题,排查起来可能会因为文本替换的复杂性而较为困难。
2024-11-09 19:33:07
962
原创 C/C++ 中的预处理器指令有哪些?举例说明其用途
假设在程序开发过程中,前面部分代码根据DEBUG_MODE宏进行调试相关操作,当调试完成后,可以通过#undef取消该宏的定义,避免对后续不需要调试的代码产生干扰。用途:这是一个因编译器而异的指令,用于向编译器传达特定的信息或指示编译器执行特定的操作。用途:用于定义宏,宏可以是常量的替换,也可以是简单的代码片段替换,以提高代码的可读性和可维护性,并且在一定程度上可以方便代码的修改。在一些编译器中,可以使用#pragma once来实现类似于头文件保护的功能,即确保一个头文件在一个源文件中只被包含一次。
2024-11-09 19:32:04
681
2
原创 只讲干货!!!如何使用函数模板和类模板?以及模板的优点是什么?
例如,对于一个已有的排序函数模板,如果要增加对新定义的数据类型的排序功能,通常只需要确保新类型满足排序所需的比较等相关条件,然后就可以直接使用该函数模板对新类型进行排序,而不需要对整个排序逻辑进行大规模的重新编写。减少代码冗余:在没有模板的情况下,如果要针对不同的数据类型实现相同的功能,就不得不为每个类型分别编写独立的函数或类,这会导致大量冗余代码的产生。而模板通过参数化类型的方式,将通用的逻辑抽象出来,使得相同的代码可以在不同的数据类型场景下复用,让代码库更加简洁、易于维护。3. 灵活性与可扩展性。
2024-11-08 16:42:58
557
原创 只讲干货!!!当你遇到别人问你时不用再说不知道,C++循环引用指的是什么,在使用过程当中需要注意什么问题
std::weak_ptr是一种弱引用,它不参与对象的引用计数管理,当需要访问被std::weak_ptr指向的对象时,可以通过std::weak_ptr的lock函数将其转换为std::shared_ptr,如果此时对象仍然存在,则可以正常访问,否则得到一个空的std::shared_ptr。对象访问延迟:由于循环引用使得对象之间的关系变得复杂,在访问其中一个对象时,可能需要通过多个指针跳转才能到达目标对象,这可能会导致对象访问的延迟,尤其是在频繁访问这些对象的情况下,会对程序的性能产生一定的影响。
2024-11-07 16:03:55
445
原创 只讲干货!!!一篇文章让你了解new或malloc在申请空间时,超出可申请的大小就会分配异常,可申请的大小是多少
例如,有些复杂的自定义类型可能包含大量的成员变量和嵌套的对象,其单个对象所需的内存空间就比较大,那么在给定的系统环境下,能成功用new 分配的该类型对象数量就相对有限。随着程序的运行,内存不断地被分配和释放,可能会导致堆内存中出现内存碎片的情况。内存碎片就是内存空间被分割成许多不连续的小块,当要malloc分配一个较大的连续内存块时,即使总的空闲内存量足够,但由于这些空闲内存分散在不同位置,无法形成足够大的连续空闲区域,那么malloc也无法成功分配出所需大小的内存。
2024-11-07 16:01:09
649
原创 只讲干货!!!请解释new和malloc的区别,并分别解释他们的用法,malloc分配失败会导致什么问题
例如,若要使用malloc分配的内存来存储整型数据,就需要将返回的void*指针转换为int*指针,即(int*)malloc(size),其中size是所需的内存大小(以字节为单位)。例如,程序在分配内存用于存储某些数据结构(如链表节点),先进行了malloc分配,若分配失败后没有正确地回滚之前已经成功分配的相关内存(假设之前已经为链表的其他部分成功分配了内存),那么这些已经分配但无法继续完成整个数据结构构建的内存就可能无法被正确释放,从而造成内存泄漏。根据所分配对象的类型返回一个指向该类型对象的指针。
2024-11-06 18:00:54
601
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人