C/C++
文章平均质量分 66
该专栏主要总结自己平时遇到的比较困惑的C/C++知识点
子非鱼Swx
路漫漫其修远兮,吾将上下而求索...
展开
-
读取位置时发生内存访问冲突
访问位置冲突异常通常是由以下几种原因引起的:原创 2023-10-14 15:43:20 · 2607 阅读 · 0 评论 -
如何用VS2019创建并调用动态库
网上查了相关资料,创建动态库主要有两种方式,一种是通过空项目创建动态库,一种是直接创建动态链接库,本文所总结的就是第二种,直接创建动态链接库。原创 2023-06-01 17:02:33 · 2854 阅读 · 0 评论 -
C/C++函数调用约定和函数名称修饰规则
对于C++的类成员函数(其调用方式是thiscall),函数的名字修饰与非成员的C++函数稍有不同,首先就是在函数名字和参数表之间插入以“@”字符引导的类名;其次是参数表的开始标识不同,公有(public)成员函数的标识是“@@QAE”,保护(protected)成员函数的标识是“@@IAE”,私有(private)成员函数的标识是“@@AAE”,如果函数声明使用了const关键字,则相应的标识应分别为“@@QBE”,“@@IBE”和“@@ABE”。如果参数类型是类实例的引用,则使用“AAV1”,对于con转载 2023-06-09 10:08:31 · 439 阅读 · 0 评论 -
静态库与动态库的区别
一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件,如果你工程里只有一个lib.h和lib.cpp,那么编译后产生的lib文件实际上就是这一个lib.obj文件的一个集合,但是如果你工程里还有其他的很多个lib.cpp文件,那么就会在编译之后生成许多lib.obj文件,然后最终只链接生成一个静态lib文件,这就是静态库。也正是因为静态库中包含了所有的静态库的.obj文件,所以静态库包含了函数的完整实现。原创 2023-05-31 14:45:42 · 1177 阅读 · 0 评论 -
匿名名称空间详解
由于这种名称空间没有名称,因此不能显示地使用using编译指令和using声明来使其在其他位置可用,具体地说,不能在匿名名称空间所在文件之的其他文件中使用该名称空间的名称,即其中的名称具有内部链接属性,作用域为所在编译单元,这提供了链接性为内部的静态全局变量的替代品。匿名的命名空间是C++的特性,相对于C的static声明来说,可以在匿名的空间里面声明很多变量和函数,这样可以省去了对每个变量和函数添加static声明,实质上匿名空间的功能跟static声明是一样的。原创 2023-03-15 10:34:56 · 316 阅读 · 0 评论 -
C++虚函数的实现机制
编译器在执行过程中遇到virtual关键字时,会为这些包含虚函数的类建立一张虚函数表vtable。在虚函数表中,编译器将按照虚函数的声明顺序依次保存虚函数地址,同时在每个带有虚函数的类中放置一个vptr指针,用来指向虚函数表。通常在定义类对象时,为vptr分配空间,该指针被置于对象的起始位置,继而通过对象的构造函数将vptr初始化为本类的虚函数表地址。原创 2023-03-14 15:12:03 · 102 阅读 · 0 评论 -
为什么派生类的构造函数必须在初始化列表中调用基类的构造函数
调用派生类的构造函数时,可能会调用继承自基类的函数,也就可能会用到基类的数据成员,因此,调用派生类的构造函数时,必须确保继承自基类的数据成员已构造完毕,而将基类构造函数的调用写在初始化列表中,能确保做到这一点。原创 2023-02-23 21:54:44 · 998 阅读 · 0 评论 -
通过一份经典的UML类图来学会如何读懂UML类图
继承关系: —▷(实线 + 空心三角形) 鸟 —▷ 动物;鸟继承动物 实现接口: •••▷ (虚线 + 空心三角形)大雁 •••▷ 飞翔;大雁实现了飞翔接口 实现接口: —○ (棒棒糖表示法) 唐老鸭 —○ 讲人话;唐老鸭实现讲人话接口 关联关系: —> (实线剪头 ) 企鹅 —> 气候;企鹅需要‘知道’气候的变化 依赖关系: •••>原创 2023-02-09 10:16:24 · 366 阅读 · 0 评论 -
C/C++数字字符与数字之间的相互转化
数字字符转化为数字就是指数字0~9转化为对应的字符‘0’~‘9’。1+'0'变成‘1’,因为‘0’对应的ASCII码值是48,1+‘0’实际上就是1+48=49,49对应的ASCII码的字符就是‘1’。‘1’-‘0’变成1,因为‘1’对应的ASCII码值是49,‘1’-‘0’实际上就是49-48=1。其余的数字字符与数字之间的转化同理。原创 2023-02-08 16:58:54 · 1908 阅读 · 0 评论 -
C/C++数字字符串与数字之间的相互转化
详细介绍了C/C++中数字与数字字符串相互转换的13种方法原创 2023-02-08 16:41:23 · 3859 阅读 · 0 评论 -
一道经典面试题透彻理解面向对象编程思想和简单工厂模式
本版本计算器代码虽然充分利用了面向对象的三大特性:封装、继承和多态,但是还是有点问题,因为最后判断到底实例化哪种运算符,是通过多个if语句判断的,这是一个典型的面向过程思想,而且该思想将界面逻辑和业务逻辑又混合了,所以我们在新版本的代码中要修改这种面向过程思想,这里我们可以利用一个设计模式,即简单工厂模式,其核心思想就是考虑用单独的类根据实际情况来创造不同类的实例。原创 2023-02-07 20:37:23 · 396 阅读 · 0 评论 -
C++访问限定符private、public、protected的使用场景
类只需要把自己的基本功能通过public成员函数作为接口提供给外部使用者。而不需要提供给外部使用者的函数,我们根据情况来设定它的访问限定符。如果仅仅只是本类成员函数要去调用的函数,我们可以封装为private,如果该函数需要继承给子类去调用,那么就将其封装为protected。这样做可以保持类对外使用的简洁性。原创 2023-02-03 15:34:00 · 1436 阅读 · 0 评论 -
vector的模拟实现
如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,可能会引起一系列浅拷贝问题,所以我们要使用赋值运算符来完成,如果不涉及资源管理,那就正常赋值,如果涉及资源管理,那赋值运算符中也已经实现了深拷贝。原创 2022-12-28 16:46:34 · 99 阅读 · 0 评论 -
string类的模拟实现
如果使用该运算符的string是const的那么就需要使用这个const版本的运算符重载。值得注意的是,原来返回引用,是因为函数结束后,变量还存在,那么我们直接返回它本身,可以减少拷贝,这里返回引用的确也可以减少拷贝,但主要的是为了使返回的变量能够被修改,如果返回的不是引用,那么返回的就是拷贝的临时变量,临时变量具有常性,是不可以被修改的。原创 2022-12-27 14:27:53 · 332 阅读 · 0 评论 -
析构函数的工作原理
如果对象是new出来的,那么它就是一个堆对象,不会被操作系统自动回收,需要我们手动调用delete函数释放该堆对象,在delete函数中会先调用析构函数释放该对象所申请的资源,那么析构函数如何释放对象所申请的资源呢,就是前面所说的,析构函数又会调用delete函数来释放对象所申请的资源,当然如果对象没有申请资源,那么就无需调用delete函数。原创 2022-11-18 20:00:27 · 1755 阅读 · 0 评论 -
构造函数的4种使用方式总结
我们无法像调用成员函数那样使用对象来调用构造函数,因为在构造函数构造出对象之前,对象是不存在的,因此构造函数被用来创建对象,而不能通过对象来调用。C++提供了多种使用构造函数初始化创建对象的方式。原创 2023-01-25 14:51:17 · 4093 阅读 · 0 评论 -
初始化列表的特性和构造函数的工作原理
所有构造函数都要先走初始化列表再走函数体,初始化列表会给每个成员都进行一次初始化,如果你的初始化列表显示初始化了某个成员,它就会去初始化,如果你没有显式初始化某个成员,它也会初始化,对于基本类型的成员变量,它会按照默认值进行初始化,如果没有设置默认值,就会用随机值进行初始化,对于自定义类型成员会调用它的默认构造函数进行初始化,如果该自定义类型的成员变量没有默认构造函数,则编译器调用构造函数创建对象的时候就会报错,因为当你没有在构造函数的初始化化列表中对自定义类型成员进行显示初始化的时候,编译器会调用自定义类原创 2023-01-25 14:48:33 · 438 阅读 · 0 评论 -
C/C++临时变量详解
左值是有内存空间的,是可以通过地址访问的的数据对象,例如变量、数组元素、结构成员、引用、解引用的指针,右值是没有内存空间,无法通过地址访问的数据对象,例如字面常量和包含多项的表达式(用引号括起来的字符串除外,它们以数组形式存储在代码段中,可由地址表示)原创 2022-10-17 19:12:35 · 3350 阅读 · 3 评论 -
读写权限详解
const变量可以赋值给const引用,但是const变量不能赋值给非const引用,因为这会造成const变量读写权限的放大,是不被允许的。const变量的地址可以赋值给const指针,但是const变量的地址不能赋值给非const指针,因为这会造成const变量读写权限的放大,是不被允许的。普通变量的赋值不会引起读写权限的改变。const普通变量可以赋值给const普通变量,const普通变量也可以赋值给非const普通变量。原创 2023-01-23 20:25:07 · 1570 阅读 · 0 评论 -
C/C++const关键字详解(全网最全)
前面提到过,读写权限只能缩小,不能放大,所以,const对象只能调用const成员函数,不可以调用非const成员函数,因为const对象不可以被修改,如果const对象调用非const成员函数,非const成员函数可以修改调用它的const对象,这是权限的放大,会报错。非const对象可以调用非const成员函数,也可以调用const成员函数,因为这是权限的缩小。原创 2023-01-19 17:46:58 · 20750 阅读 · 12 评论 -
extern“C“关键字详解
如果没有条件编译和extern “C”,那么对于C++代码,编译器对C++代码按照C++的方式处理,在编译和汇编阶段形成符号表时就是按照C++的方式用符号表示函数,对于C代码,编译器按照C的方式处理,在编译和汇编阶段按照C的方式用符号表示函数,由于C和C++对函数名的修饰规则不同,因此,对于同一函数,C和C++表示函数的符号就不同,那么在链接阶段就无法通过符号名找到相应函数的地址,那么就会产生链接错误。原创 2022-10-13 18:17:06 · 1743 阅读 · 0 评论 -
explicit关键字详解
在C++中,explicit关键字用来修饰类的构造函数,被explicit修饰的类的构造函数,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。原创 2022-12-16 09:46:47 · 2532 阅读 · 0 评论 -
程序的预编译、编译、汇编、链接详解
预编译主要会对源文件进行一系列文本操作,包括头文件的包含,删除注释,#define定义符号的替换,条件编译等。我们执行可以gcc -E text.c指令对程序进行预编译,预编译后的结果会直接输出在屏幕上,但是我们一般执行gcc -E text.c -o text.i指令将预编译后的结果输出为text.i文件。同理,我们对add.c进行同样的操作得到add.i文件。预编译完成后,编译器就会对生成的text.i文件和add.i文件进行编译了,将C语言代码编译为汇编代码,编译阶段的主要操作就是语法分析,语义原创 2022-04-16 17:23:38 · 1933 阅读 · 0 评论 -
如何避免头文件被重复包含?
加入了这些预编译处理指令后,第一次包含该头文件的时候,__ TEXT_H__没有被定义,条件为真,那么就会对其中的内容进行预编译处理,所以就会定义__ TEXT_H__,并且头文件的内容会被预编译,也就是会被包含,第二次包含该头文件的时候,__ TEXT_H__已经被定义了,条件为假,就不会对其中的内容进行预处理,也就不会再定义__ TEXT_H__,不会包含头文件的内容。这样就可以避免头文件的重复包含。原创 2023-01-18 11:38:37 · 2438 阅读 · 1 评论 -
VS2019实用调试技巧
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,编译器对我们写的代码进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用,Release版本不能调试。原创 2022-05-19 17:45:13 · 7145 阅读 · 0 评论 -
C语言输入输出格式总结
本篇文章主要总结C语言输入输出格式原创 2022-09-29 22:45:53 · 731 阅读 · 0 评论 -
C/C++清理输入缓冲区中的内容
1.清理输入缓冲区最后剩下的单个回车符:方法一:用getchar函数读取回车符,方法二:用scanf("%*c")读取掉回车符,方法三:用scanf(" %c",&ch)。 2.清理输入缓冲区中剩下的所有内容:方法一:用getchar函数结合循环语句,方法二:用scanf("%*[^\n]"):原创 2022-05-14 11:21:12 · 9590 阅读 · 2 评论 -
C语言rand()函数产生随机数详解
在调用rand函数之前,会先查询是否主动调用过srand(seed)来为伪随机数生成器设定种子,如果有,那么就按照我们的代码设定种子,即初始化seed的起始值,若没有调用srand(seed),那么系统会自动给seed赋初始值,即自动调用srand(1)一次,也就是将seed的值设置为1。如果每次调用rand函数时,种子相同,那么根据公式产生的伪随机数将是相同的。原创 2022-09-28 21:13:01 · 35599 阅读 · 14 评论 -
C/C++缓冲区
输入缓冲区通常是一种行缓冲区,程序并不会立即获取键盘输入的数据,键盘输入的数据都会存储在输入缓冲区中,按下回车键后,输入缓冲区遇到回车符,程序才从输入缓冲区读取数据(回车符也会存储在输入缓冲区中)。输出缓冲区通常也是一种行缓冲区,当有多个连续输出时,为了减少系统调用,程序不会立即把数据输出到屏幕上,而是先存储在输出缓冲区中,当遇到换行符,会输出缓冲区中的数据到外部设备上。原创 2023-01-18 11:05:58 · 1012 阅读 · 0 评论 -
如何读取字符串中的空格
在scanf中使用%[ ]参数。这个参数的作用就是读取一个字符集合。[]中括号里面输入读取的字符集合。比如%[a-z]读取a到z的字符集合。要读取一行只要,只要设置为读取非换行符就可以了%[^\n]原创 2022-06-16 17:04:48 · 3573 阅读 · 2 评论 -
scanf语句的使用和执行原理
这说明scanf语句读取完数字后,会把后面的空格也读取掉。如果后面有变量来接收,读取后就会把空格赋值给对应的变量,如果没有变量来接收,那么仅仅是读取,不会进行赋值操作。值得注意的是,scanf只有在读取完数字后会继续把后面的空格读取掉原创 2022-02-07 11:10:31 · 13017 阅读 · 1 评论 -
C/C++数据类型转换详解
自动类型转换常被称为隐式类型转换,强制类型转换常被称为显示类型转换,强制类型转换的一般形式为(类型标识符)(操作数)或(类型标识符)(表达式)。其功能就是把操作数或表达式结果的数据类型暂时地强制转换为圆括号()中的类型。原创 2023-01-14 08:31:19 · 5451 阅读 · 0 评论 -
数组名的意义
那么arr+i就是指向第i+1行数组,相当于第i+1行的数组地址,*(arr+i) 相当于第i+1行的数组,第i+1行数组可以看作第i+1行的数组名,通常情况下数组名表示数组首元素的地址,所以 *(arr+i)也是第i+1行数组首元素的地址。原创 2023-01-14 08:20:20 · 2472 阅读 · 0 评论 -
static关键字的作用
函数也是具有外部连接属性的,编译器每次编译只处理一个编译单元,当某个编译单元需要使用其他编译单元中的函数,只需要声明该函数(或者包含该函数声明所在的头文件)然后就可以使用,当一个函数被static所修饰的时候,这个函数的外部连接属性就变成了内部连接属性,也就成为了静态函数,使得这个静态函数只能在自己所在的编译单元中被使用,而不能被其它编译单元所使用,否则会出现链接性错误。原创 2023-01-14 08:13:42 · 8546 阅读 · 0 评论