自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 C++中的接口继承和实现继承以及多态性与性能的平衡处理

而对于attack等函数,因为不同角色(如战士、法师)的攻击方式差异较大,需要多态性来实现不同的行为,这时可以通过合理的类设计和虚函数调用,同时注意对关键性能路径的优化,如在update函数中尽量减少虚函数调用,来平衡多态性和性能。例如,在一个简单的图形绘制系统中,如果对于大多数基本形状(如简单的矩形、圆形),绘制函数的行为是固定的,那么可以将这个绘制函数在基类中定义为非虚函数,以避免虚函数调用的开销。接口继承是指子类只继承基类的纯虚函数,即只继承基类的接口,而不继承基类的实现。实现继承侧重于代码复用。

2024-12-15 22:31:19 641

原创 C++中的动态绑定和内存管理

3.智能指针(C++11 引入)用于自动内存管理内存的分配和释放,避免内存泄漏和悬挂指针的问题unique_ptr:它是一种独占式智能指针,一个unique_ptr对象独占它所管理的资源。同时,合理的内存管理可以提高程序的性能,减少内存分配和释放的开销。它允许在不修改现有代码的情况下,通过添加新的派生类来扩展程序的功能,并且能够在运行时根据具体的对象类型选择合适的函数调用。首先在基类中定义虚函数。在对象销毁时,析构函数可以释放资源 例如,对于动态分配的内存,可以在构造函数中进行分配,在析构函数中进行释放)

2024-12-15 21:34:41 488 1

原创 C++中的静态链接和动态链接

因为它将所有需要的库代码和数据都包含在可执行文件中,即使不同的程序使用了相同的库函数,每个程序在静态链接后都会有一份完整的库代码副本。例如,多个 C 程序都使用了标准的printf函数,如果是静态链接,每个程序的可执行文件中都会包含printf函数的代码,这会占用大量的磁盘空间。例如,一个软件系统使用了一个动态的数据库访问库,当数据库访问库的开发者修复了库中的一个安全漏洞或者优化了性能后,只要将新的动态链接库替换原来的旧库,所有使用这个库的软件就可以受益于这些更新,而不需要对软件本身进行重新编译和发布。

2024-12-04 21:33:48 377

原创 C++中的函数重载

例如在 C++ 中,编译器可能会把函数名和参数信息编码成一个复杂的符号,编译器可能会将int add(int a, int b)修饰为类似_add_int_int(这只是一个简单示意,实际的名字修饰规则因编译器而异),int add(int a, int b, int c)可能修饰为_add_int_int_int,float add(float a, float b)可能修饰为_add_float_float。名字修饰是一种机制,它根据函数的参数类型,参数数量等信息来生成一个唯一的内部名称。

2024-12-01 21:09:48 626

原创 C++和C中的volatile 关键字

例如,当编译器发现一个变量的值在一段代码中没有被显式地改变时,它可能会将这个变量的值缓存到寄存器中,后续对这个变量的读取操作就直接从寄存器中获取值,而不是从内存中读取。volatile关键字就是告诉编译器,这个变量是 “易变的”,不要对它进行这种优化,每次访问这个变量都要从内存中读取,每次修改这个变量也要及时写回内存。volatile关键字强调变量是易变的,主要用于告诉编译器不要对变量的访问进行优化,重点在于变量值的不确定性(可能被外部因素改变),而不是限制变量的修改。2.多线程环境中的可见性。

2024-11-28 22:05:01 461

原创 C++ 中的 Lambda 表达式

一般情况下,不指定lambda表达式的返回值,编译器会根据return语句自动推导返回值类型,但是需要注意的是lambda表达式不能通过列表初始化自动推导出返回值类型,因为不知道列表是哪种类型(有vector,list等等),需要正确显示声明了函数的返回值类型是哪种类型的。与任何函数相似,一个lambda表达式具有一个返回类型,一个参数列表,一个函数体,但与函数不同,lambda表达式可以定义在函数内部。[=]捕获外部作用域的所有变量,按照值捕获,拷贝过来的副本在函数体内是只读的。[ ] 不捕获任何变量。

2024-11-25 19:11:33 361

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

当你在代码中写vector时,编译器可能会混淆你到底是想使用自己定义的vector还是std中的std::vector,从而导致编译错误或者运行时的逻辑错误。下面是定义一个模板类型别名来表示std::vector的某种特定类型(这里以int为例),这样就可以方便地使用MyVector来创建不同类型的vector。优点:可以提高代码的可读性和可维护性,减少代码的重复(特别是当涉及到复杂的类型或者需要在代码中多次使用相同的类型定义时)缺点:可能会导致命名冲突,如果不小心使用了相同的别名或引入了不适当的名称。

2024-11-25 19:06:27 412

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

MyTemplate 是为 T1 是指针类型、T2 是任意类型的情况特化的版本,它覆盖了通用模板中的 print 方法,提供了专门的行为。需要注意的是,在使用模板特化和偏特化时,要确保特化和偏特化的版本在语义和功能上与通用模板保持一致或有合理的特殊用途,并且要注意模板特化和偏特化的匹配规则,编译器会根据最匹配的版本来生成代码。例如,对于一个通用的模板函数,它可以处理多种类型的数据,但对于某些特定类型(如int或char*),可能需要一种完全不同的实现方式来提高效率或满足特殊需求。

2024-11-23 23:51:13 444

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

智能指针本质上是一个类模板(因为智能指针需要能够管理不同类型的对象以及它的核心功能与所管理对象的具体类型是无关的),它的行为类似于普通指针,但在对象的生命周期管理上更加智能。当一个对象被拷贝时,会创建一个新的对象,这个新对象的内容是原始对象的完全副本,这意味着新对象和原始对象在内存中有独立的存储空间,并且它们包含相同的值。移动语义则是一种资源所有权的转移,它主要用于将一个对象通常是临时对象或即将被错毁的对象)的资源(如动态分配的内存文件句柄等)直接转移给另一个对象,而不是进行复制。

2024-11-22 22:04:18 389

原创 C++ 中的移动语义

在函数内部,将other对象的data指针赋值给新对象的data指针,然后将other对象的data指针设置为nullptr,这样就实现了资源(字符串内容)从一个对象到另一个对象的 “移动”,而不是复制。然后释放当前对象的资源(delete[] data),接着将other对象的资源(data指针)赋值给当前对象,最后将other对象的data指针设置为nullptr,完成资源的移动赋值。通过移动语义,可以将对象的资源从一个对象转移到另一个对象,从而避免不必要的内存拷贝,提高程序性能和效率。

2024-11-22 21:41:02 1482

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

对于一些需要在构造函数体内进行复杂计算的成员变量,可以先在初始化列表中进行默认初始化,然后在构造函数体内进行赋值。当一个类的数据成员是另一个类的对象,并且这个对象的类没有默认构造函数(只有带参数的构造函数)时,必须使用初始化列表来初始化该数据成员。初始化列表:初始化列表中的初始化操作是按照成员变量在类中声明的顺序进行的,而不是按照初始化列表中的书写顺序。在对象创建时,对成员变量进行初始化,特别是对于const成员变量,引用成员变量和没有默认构造函数的成员对象,必须用初始化列表进行初始化。

2024-11-20 21:00:13 599

原创 友元类和友元函数

友元函数的声明以friend关键字开头,在类的内部进行声明,但它的定义在类的外部,和普通函数一样。友元类是被另一个类声明为 “朋友” 的类。例如,如果B类是A类的友元类,那么B类中的所有成员函数(fast)都可以访问和修改A类的私有成员。若类 B是类 A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。当一个类被声明为另一个类的友元类时,友元类的所有成员函数都可以访问被访问类的私有成员。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

2024-11-18 22:38:28 436

原创 C++内联函数

1.inline是一种以空间换时间的做法,省去调用函数,建立栈帧得额外开销,但是如果代码很长(一般是10行左右,具体取决于编译器),或者有递归函数,即使函数前面声明了inline,那么编译器也不会让该函数成为内联函数。内联函数的定义:以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,如果没有压栈的开销,内联函数提升程序运行的效率。2.如果不加inline不一定不是内联函数,存在隐式内联,不用inline关键字,C++中在类内定义的所有函数都自动称为内联函数。

2024-11-18 17:05:51 296

原创 C++和C中的类型转换方式以及带来的问题

例如,将一个较大的unsigned long long类型的值转换为unsigned int类型,这里b的值超出了unsigned int所能表示的最大值(4294967295),在隐式转换时会发生数据溢出,导致s的值不符合预期,可能会出现循环计数错误等问题。例如,在一个比较复杂的表达式中:因为a会被隐式转换为double类型后再与b相加,浮点数的存储和运算可能会产生微小的误差,使得a + b的结果在比较时可能不等于1.5,从而导致程序进入错误的逻辑分支。2.将小范围的整数类型自动转换为大范围的整数类型。

2024-11-17 00:21:32 710 1

原创 C++中的常量表达式

而b是用a + 5初始化的,因为a是常量表达式,5也是常量表达式,所以a + 5这个算术表达式在编译阶段可以计算出结果,因此b也是常量表达式。在C++中,常量表达式是指在编译期间就能计算出其值的表达式,并且该值在程序运行过程中不会改变,编译器可以在编译时就确定它的值。在初始化枚举常量时,可以使用常量表达式。1.定义数组大小:定义数组时,数组的大小必须是一个常量表达式,因为数组在内存中的空间是在编译时就分配好的。3.枚举类型的值 例如,Color::Green是一个常量表达式,它的值是2在编译时就已经确定。

2024-11-17 00:08:55 1757

原创 C++函数的返回值在内存中的传递过程以及虚拟内存

在调用函数的地方,需要注意对返回的指针进行正确的内存管理,比如及时释放动态分配的内存,防止内存泄漏。如果返回的是一个局部变量的指针,同样会出现问题,因为当函数结束后,局部变量的内存被释放,返回的指针就会指向无效的内存区域。如果返回的是一个局部变量的引用,这是非常危险的,因为当函数结束时,局部变量的内存会被释放,返回的引用就会成为一个悬空引用。例如,在一个多任务操作系统中,同时运行的多个程序(进程),如一个文本编辑器和一个浏览器,它们的内存空间是相互隔离的,不会因为一个进程的错误操作而影响到其他进程。

2024-11-15 00:32:27 1867

原创 C++ 中的异常处理机制以及异常处理的优缺点

在这个例子中,function2()抛出了一个异常,由于它本身没有try - catch块来捕获这个异常,所以异常会传播到function1(),function1()也没有捕获机制,所以异常会继续传播到main()函数。异常的传播如果在一个函数中抛出了异常,而这个函数本身没有try - catch机制来捕获这个异常,那么这个异常会沿着函数调用栈向上传播,直到找到一个能够处理这个异常的try - catch块。例如:在这个例子中,try块中的代码尝试进行除法运算,当除数为零时,就会抛出一个异常。

2024-11-14 00:23:09 689

原创 C++命名空间以及命名空间的使用和嵌套

例如,你自己写了一个函数叫max,同时又引入了一个标准库中的std::max。通过将它们放在不同的命名空间中(如你的my_lib命名空间和std命名空间),就可以明确地区分它们,像my_lib::max和std::max。比如,你可以为一个图形库创建一个命名空间Graphics,在这个命名空间下包含Shape类(用于表示图形形状)、draw函数(用于绘制图形)等所有与图形相关的代码。,后面跟着命名空间的名字,然后在花括号{}内定义该命名空间中的各种标识符(如类、函数、变量等)。命名空间基本语法是使用。

2024-11-14 00:13:53 449

原创 C/C++ 中的预处理器指令以及宏定义和函数调用的区别

例如,如果定义了#define MULTIPLY(a,b) (a*b),然后使用MULTIPLY(3, "abc"),预处理器仍然会进行替换,在编译阶段可能会导致错误,因为这里试图将整数和字符串相乘。例如,对于宏定义#define ADD(x,y) ((x)+(y)),在预处理时,像int result = ADD(3, 4);当程序执行到函数调用语句时,会保存当前的执行上下文(如寄存器的值、栈指针等),然后跳转到函数的入口地址执行函数体中的代码,执行完后再返回原来的执行点继续执行。

2024-11-10 17:32:47 620

原创 使用函数模板和类模板以及模板的优点

myObj1中的成员变量m_data是int类型,myObj2中的m_data是double类型,它们的getData函数返。这里template 定义了类模板,MyClass是一个类模板,它有一个成员变量m_data和一个成员函数。int类型,所以自动将模板参数T推导为int,并生成一个对应的函数版本,就好像我们定义了一个普。例子中,函数的返回值是double类型相加的结果,但是我们将它赋值给了一个int类型的变量。模板允许编写通用的代码,可以处理多种不同类型的数据,而不需要为每种数据类型都编写重。

2024-11-10 00:38:07 786

原创 new和malloc可申请的空间大小以及智能指针和C++循环引用

在这个例子中,student1通过shared_ptr持有course1的引用(在student1->courses向量中),同。shared_ptr引用Student对象,能够控制Student对象的生命周期,而Student对象通过weak_ptr引。当file_ptr的引用计数为0时,shared_ptr内部维护一个引用计数,用于记录有多少个shared_ptr对象指向同一个底层对象。这行代码创建了一个shared_ptr对象p1,它指向一个新分配的int类型对象,该对象的值被初始化为。

2024-11-10 00:19:26 814

原创 new和malloc的区别以及malloc分配失败导致的问题

而new返回的是所分配对象类型的指针,如new int返回int* ,new MyClass(MyClass是一个自定。在分配数组时,传入数组元素的个数,如new int[10]会分配能存储 10 个int类型数据的连。另外,new还可以在分配对象的同时进行初始化,例如new int(5)会分配一个int类型。而new在分配单个对象时,不需要传入字节数,例如new int会自动根据int类型的大小分配足够的内。new int在堆上分配了足够存储一个int类型数据的空间,并返回指向该空间的int类型指针。

2024-11-07 14:16:06 778

原创 拷贝构造函数和赋值运算符重载的作用以及c++模板

它的形式通常是ClassName(const ClassName& other),其中other是要复制的对象。(简单的赋值拷贝操作) 两个对象里面的指针成员变量指向同一块堆区内存,会造成同一块堆。:函数模板是一种通用的函数定义,可以用于生成多个不同类型的具体函数。:赋值运算符简单来说就是浅拷贝,编译器会提供默认的赋值运算符,就是成员变量的。允许自定义对象赋值的操作,默认情况下,C++ 提供了浅赋值操作,但在许多情。:C++ 模板是一种泛型编程机制,它允许编写能够处理多种数据类型的代码,而。

2024-11-07 00:09:54 295

原创 C++的三大特性及构造函数和析构函数

Vehicle,Car类就自动拥有了speed变量和drive()函数避免了代码的重复编写,通过重写drive方。例如下面这个基类Vehicle,它有成员变量speed和成员函数drive(),然后有一个派生类Car继承自。例如下面这个银行账户类, 它是由属性(账户余额)和行为(存款,取款)构成了独立的单元,来体现。public://公有权限:可以类内(成员方法)访问,子类访问,对象访问(通过.访问)用虚函数,实际调用的是派生类中重写后的虚函数,这是在运行时根据对象的实际类型来决定的。

2024-11-06 21:30:37 439

原创 结构体和联合体的区别和能否在声明过程当中缺省名字以及结构体是否可以包含函数

名和成绩的结构体:在内存中,name数组占据一段连续的内存空间,score也占据自己独立的内存。如果先给i赋值,然后访问f,f的值将是根据i的值在内存中的存储方式重。与 C 语言略有不同,在 C++ 中,匿名联合体的成员可以直接访问,就像它们是外层作用域的成员。这里定义了一个没有名字的结构体类型,同时创建了一个该类型的变量myVar。共用体也称联合是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。处理通信协议时,一个数据包可能有多种格式,根据不同的协议类型,数据包的内容有不同的解。

2024-11-06 16:29:39 658

原创 C、C++中字符串的存储方式以及C下用函数模拟字符串的比较

将源字符串(包括结束符'\0')复制到目标字符串中,覆盖目标字符串原来的内容。符'H','e','l','l','o'依次存放在连续的内存单元中,并且在字符串的末尾自动添加'\0'(ASCII 码。将源字符串(不包括源字符串的'\0'起始位置)添加到目标字符串的'\0'位置处,然后更新目标字符串的'\0'位置。判断结束,如果在处理字符串时不小心修改了'\0',或者字符串没有正确地以'\0'结尾,就可能导致。的第一个字符开始,逐个字符进行比较,直到发现不相等的字符或者到达字符串的结束符'\0'。

2024-11-06 14:07:42 711

原创 数组的定义和初始化以及数组名的含义

例如,int m[][4] = {{1, 2, 3, 4}, {5, 6, 7,8}, {9, 10, 11, 12}},编译器会根据初始。数据类型 数组名[行数][列数] 例如,int m[3][4]定义了一个名为m的二维整形数组,它有 3 行 4 列,总共可以存储 3*4 = 12 个整数。例如,int m[3][4] = {{1, 2, 3, 4}, {5, 6, 7,= {1, 2, 3, 4, 5},编译器会根据初始化列表中的元素个数自动确定数组的大小为 5。例如,int arr[]

2024-11-04 18:30:02 350

原创 new 和 delete 运算符以及内存泄漏

例如,如果有int* ptr = new int,在使用完该内存后,可以使用delete ptr来释放该内存。new在堆上分配所需的内存空间 例如,int* ptr = new int会在堆上分配足够存储一个整数的内存空间,并返回一个指向该内存地址的指针。在 C++ 中,如果使用new和delete手动管理内存,要确保在合适的时机调用delete来释放内存。C++11 引入了智能指针,如unique_ptr和shared_ptr,它们可以自动管理内存的分配和释放,大大减少了内存泄漏的风险。

2024-10-31 23:33:40 457

原创 空指针和野指针及C/C++中内存分区

智能指针可以自动管理内存的分配和释放,避免手动管理内存带来的错误,从而减少野指针的出现。空指针的主要作用是提供一种安全的方式来表示指针当前没有指向任何有效的对象,这样在程序中可以通过检查指针是否为空来避免对无效内存地址的访问。需要注意的是,堆上的内存分配和释放相对较慢。野指针是指一个指针变量指向了一个不可预测的内存地址,这个地址可能是已经被释放的内存、未分配的内存或者是无效的地址。如果一个函数返回一个局部变量的地址,当函数返回后,这个局部变量的内存可能会被回收,而返回的指针就成为了野指针。

2024-10-31 23:27:19 337 1

原创 指针的定义和用途以及指针和引用的区别

例如,在 C 语言中:这里a是一个指针,它指向一块可以存储 10 个整数的动态分配的内存空间,之后可以通过指针a来访问和操作这块内存。这里ref就是a的引用,它和a代表同一个变量),而指针是一个实体,需要通过 解引用来访问所指向的对象;例如,下面的函数用于交换两个整数的值,当调用swap(&a, &b)时,函数可以通过指针修改a和b的值。●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;指针指向一块内存,它的内容是所指内存的地址;

2024-10-29 23:46:12 516

原创 递归函数的特点和使用场景以及回调函数的定义和特点

如果想要在分析数据之后添加一个新的功能,比如数据可视化,可以通过将数据可视化的函数作为回调函数传递给分析数据的函数或者整个数据处理管道,在适当的位置调用这个新的回调函数,从而实现功能的扩展,而无需对原有的数据处理函数进行大规模的修改。以斐波那契数列为例,F(n)=F(n - 1)+F(n - 2)(n > 1),它将计算第n个斐波那契数的问题分解为计算第n - 1个和第n - 2个斐波那契数的子问题,直到分解到n = 0或n = 1(此时F(0)=0,F(1)=1)。这是递归函数中至关重要的部分。

2024-10-28 19:37:01 594

原创 switch-case语句的注意事项及函数参数传递的方式和特点

正确的做法是每个case分支应该有唯一的常量值与之对应,这样才能确保程序在执行switch - case语句时,对于switch表达式的每一个可能的值,都有明确唯一的执行路径。在值传递方式中,函数的形参是实参的副本。swap函数试图交换两个整数的值,但由于是值传递,函数内部的操作只是对num1和num2的副本进行操作,所以在函数调用结束后,num1和num2的值没有改变。swap函数的参数是引用类型,函数内部对a和b的操作实际上就是对num1和num2本身的操作,所以num1和num2的值被成功交换。

2024-10-27 23:21:48 899

原创 C语言中的三种基本控制结构

然后通过while语句判断j是否小于等于5,如果为真,就执行循环体中的语句,输出j的值,然后j自增1。然后判断i是否小于等于5(这是for循环的条件判断部分), 如果条件为真,就执行循环体中的语句,即输出i的值。//代码解释 在这个for循环中,变量i从1开始,每次循环i的值增加1,循环条件是i <= 10。所以程序只会输出1 2 3 4,然后跳过循环中i = 5及之后的部分,直接执行循环后面的printf语句,输出 “循环结束后的语句”。} printf("\n循环结束后的语句");int b = 3;

2024-10-26 23:51:11 542

原创 三目运算符和运算符的优先级

首先计算条件表达式的值 如果条件表达式的值为真(非零值表示真),那么整个三目运算符表达式的值为值1;如果条件表达式的值为假(通常零值表示假),那么整个三目运算符表达式的值为值2。运算符的优先级是指在一个包含多种运算符的表达式中,确定先计算哪些运算符,后计算哪些运算符的规则。如何运用三目运算符 比较三个数 选出最大值或者最小值,写出对应代码。下面给出的是一些容易混淆的运算符优先级示例。2) 解释一下三目运算符(?用法: 条件表达式?运算符的优先级决定了计算的先后顺序。1)什么是运算符优先级?

2024-10-25 19:40:38 421

原创 C语言中的枚举

在C语言中,枚举类型是被当做int或者unsigned int类型来处理的,所以按照C语言规范是没有办法遍历枚举类型的,不过在一些特殊情况下,枚举类型必须连续是可以实现有条件遍历的。枚举是一种用户定义的数据类型,它允许你定义一组命名的常量。2.枚举类型可以提供更好的代码可维护性,当需要修改一个常量时,只需要在枚举定义中修改即可,而不需要在程序的其它地方寻找所有使用了这个常量。:1.第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1;enum 枚举名 {枚举元素1,枚举元素2,...};

2024-10-24 23:55:05 234 2

空空如也

空空如也

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

TA关注的人

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