|
发表于 7 小时前
|
查看: 11 |
回复: 0
本帖最后由 jinchanchan 于 2025-5-9 13:17 编辑
36.完美转发的原理是什么?
完美转发是指函数模板可以将自己的参数完美的转发给内部调用的其他函数,完美是指不仅能够准确的转发参数的值,还能保证被转发参数的左、右值属性不变,使用引用折叠的规则,将传递进来的左值以左值传递出来,将传递进来的右值以右值的方式传出。
37.空类中有什么函数?
默认构造函数、默认拷贝构造函数、默认析构函数、默认赋值运算符
取值运算符、const取值运算符
38.explicit用在哪里?有什么作用?
只能用于修饰只有一个参数的类构造函数(有一个例外就是,当除了第一个参数以外的其他参数都有默认值的时候此关键字依然有效),它的作用是表明该构造函数是显示的,而非隐式的,跟它对应的另一个关键字是implicit,意思是隐藏的,类构造函数默认情况下声明为implicit。作用是防止类构造函数的隐式自动转换。
39.成员变量初始化的顺序是什么?
成员变量在使用初始化列表初始化时,与构造函数中初始化成员列表的顺序无关,只与定义成员变量的顺序有关。如果不使用初始化列表初始化,在构造函数内初始化时,此时与成员变量在构造函数中的位置有关。类中const成员常量必须在构造函数初始化列表中初始化。类中static成员变量,只能在类外初始化。
顺序:基类的静态变量或全局变量,派生类的静态变量或者全局变量,基类的成员变量,派生类的成员变量。
40.指针占用的大小是多少?
64位电脑上占8字节,32位的占4字节,我们平时所说的计算机多少位是指计算机CPU中通用寄存器一次性处理、传输、暂时保存的信息的最大长度。即CPU在单位时间内能一次处理的二进制的位数,因此CPU所能访问的内存所有地址由多少位组成,而8比特位表示1字节,就可以得出在不同位数的机器中指针的大小。
41.野指针和内存泄漏是什么?如何避免?
内存泄漏:是指程序中以动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果
避免:使用智能指针管理资源,在释放对象数组时使用delete[],尽量避免在堆上分配内存
野指针:指向一个已删除的对象或未申请访问受限内存区域的指针。
避免:对指针进行初始化,用已合法的可访问内存地址对指针初始化,指针用完释放内存,将指针赋值nullptr。
42.malloc和new的区别是什么?
Malloc/free是标准库函数,new/delete是C++运算符
Malloc分配内存失败返回空,new失败抛异常
New/delete会调用构造析构函数,malloc/free不会,所以他们无法满足动态对象的要求。
New返回有类型的指针,malloc返回无类型的指针
分配内存的位置:malloc从堆上动态分配内存,new是从自由存储区为对象动态分配内存(取决于operator new的实现,可以为堆还可以是静态存储区)
New申请内存的步骤:调用operator new函数,分配一块足够大,且原始的,未命名的内存空间来存储特定类型的对象。运行相应的构造函数来构造对象,并为其传入初值,返回一个指向该对象的指针。
Delete:先调用对象的析构函数,再调用operator delete函数释放内存空间
43.多线程会发生什么问题?线程同步有哪些手段?
会引发资源竞争的问题,频繁上锁会导致程序运行效率低下,甚至会导致发生死锁。
线程同步手段:使用atomic原子变量,使用互斥量也就是上锁,使用条件变量或信号量制约对共享资源的并发访问。
44.什么是STL?
它是C++标准库的重要组成部分,不仅是一个可复用的组件库也是一个包含了数据结构与算法的软件架构,它拥有六大组件分别是:仿函数,算法,迭代器,空间配置器,容器,配接器
45.对比迭代器和指针的区别
迭代器不是指针,是一个模板类,通过重载了指针的一些操作符模拟了指针的一些功能,迭代器返回的是对象引用而不是对象的值。
指针能够指向函数而迭代器不行迭代器只能指向容器
46.线程有哪些状态,线程锁有哪些?
五种状态:创建,就绪,运行,阻塞,死亡
线程锁的种类:互斥锁,条件锁,自旋锁,读写锁,递归锁
47.解释说明一下map和unordered_map
Map内部实现是一个红黑树,内部所有的元素都是有序的,而hashmap则是内部实现了一个哈希表,内部存储元素是无序的
Map优点:有序性,其次是内部实现的是一个红黑树,使得很多操作都可以在logn的复杂度下可以实现效率较高。
Map缺点:空间占用率高
Unorderedmap优点:查找效率非常高。缺点:哈希表的建立比较费时间
48.vector中的push_back()和emplace_back()的区别、以及使用场景
当使用Push_back时会先调用类的有参构造函数创建一个临时变量,再将这个元素拷贝或者移动到容器之中,而emplace_back则是直接在容器尾部进行构造比push_back少进行一次构造函数调用。在大部分场景中emplace_back可以替换push_back,但是push_back会比emplace_back更加安全,emplace_back只能用于直接在容器中构造新元素的情况,如果要将现有的对象添加到容器中则需要使用push_back
49.如何实现线程安全,除了加锁还有没有其他的方式?
除了锁之外还可以使用互斥量(防止多个线程来同时访问共享资源,从而避免数据竞争的问题),原子操作(原子操作是不可分割的,使用原子操作可以确保在多线程环境中操作是安全的),条件变量(协调线程之间的协作,用来在线程之间传递信号,从而控制线程的执行流程)等方式
50.vector扩容,resize和reserve的区别
使用resize改变的是vector的大小(size),可能会添加或删除元素。
使用reserve改变的是vector的容量(capacity),不会改变当前元素的数量,仅仅是为了优化内存使用和性能。
51.vector扩容为了避免重复扩容做了哪些机制?
当vector内存不够时本身内存会以1.5或者2倍的增长,以减少扩容次数
引入了reserve,自定义vector最大容量
52.C++中空类的大小是多少?
1字节
53.weak_ptr是怎么实现的?
实现依赖于计数器和寄存器实现的,计数器用来记录弱引用的数量,寄存器用来存储shared_ptr
54.虚函数的底层原理是什么?
虚函数表和虚表指针,详细看本文第四问。
55.一个函数f(int a,int b),其中a和b的地址关系是什么?
a和b的地址是相邻的。
56.移动构造和拷贝构造的区别是什么?
移动构造函数本质上是基于指针的拷贝,实现对堆区内存所有权的移交,在一些特定场景下,可以减少不必要的拷贝。比如用一个临时对象或者右值对象初始化类实例时。我们可以使用move()函数,将一个左值对象转变为右值对象。而拷贝构造则是将传入的对象复制一份然后放进新的内存中
57.lamda表达式捕获列表捕获的方式有哪些?如果是引用捕获要注意什么?
按值捕获和引用捕获,默认的引用捕获可能会导致悬挂引用,引用捕获会导致闭包包含一个局部变量的引用或者形参的引用,如果一个由lambda创建的闭包的生命周期超过了局部变量或者形参的生命期,那么闭包的引用将会空悬。解决方法是对个别参数使用值捕获
58.哈希碰撞的处理方法
开放定址法:当遇到哈希冲突时,去寻找一个新的空闲的哈希地址。
再哈希法:同时构造多个哈希函数,等发生哈希冲突时就使用其他哈希函数知道不发生冲突为止,虽然不易发生聚集,但是增加了计算时间
链地址法:将所有的哈希地址相同的记录都链接在同一链表中
建立公共溢出区:将哈希表分为基本表和溢出表,将发生冲突的都存放在溢出表中
59.unordered_map的扩容过程
当unordered_map中的元素数量达到桶的负载因子(0.75)时,会重新分配桶的数量(通常会按照原有桶的数量*2的方式进行扩容,但是具体的增长策略也可以通过修改容器中的max_load_factor成员变量来进行调整),并将所有的元素重新哈希到新的桶中。
60.vector如何判断应该扩容?(size和capacity)
由当前容器内元素数量的大小和容器最大大小进行比较如果二者相等就会进行扩容,一般是1.5倍,部分的有两倍
61.构造函数是否能声明为虚函数?为什么?什么情况下为错误?
构造函数不能为虚函数,虚函数的调用是通过虚函数表来查找的,而虚函数表由类的实例化对象的vptr指针指向,该指针存放在对象的内部空间之中,需要调用构造函数完成初始化,如果构造函数为虚函数,那么调用构造函数就需要去寻找vptr,但此时vptr还没有完成初始化,导致无法构造对象。
62.类中static函数是否能声明为虚函数?
不能,因为类中的static函数是所有类实例化对象所共有的,没有this指针,而虚函数依靠vptr和vtable来处理,vptr是一个指针,在类中的构造函数中生成,并且只能通过this指针访问,对于静态成员函数来说,他没有this指针,无法访问vptr,因此static函数无法声明为虚函数
63.哪些函数不能被声明为虚函数?
构造函数,内联函数(内联函数有实体,在编译时展开,没有this指针),静态成员函数,友元函数(C++不支持友元函数的继承),非类成员函数
64.如何保证类的对象只能被开辟在堆上?(将构造函数声明为私有、单例)
将构造函数设置为私有,这样只能使用new运算符来建立对象,但是我们必须准备一个destory函数来进行内存的释放,然后将析构函数设置为protected,提供一个public的static函数来完成构造,类似于单例模式
如果在栈上分配呢?则是重载new操作符,使得new操作符的功能为空,这样就使得外层程序无法在堆上分配对象,只可以在栈上分配
65.讲讲你理解的虚基类
虚基类是 C++ 中一种特殊的类,用于解决多继承所带来的“菱形继承”问题。如果一个派生类同时从两个基类派生,而这两个基类又共同继承自同一个虚基类,就会形成一个“菱形”继承结构,导致派生类中存在两份共同继承的虚基类的实例,从而引发一系列的问题。
为了解决这个问题,我们可以将虚基类作为共同基类,并在派生类中采用虚继承的方式。
虚继承会使得派生类中只存在一份共同继承的虚基类的实例,从而避免了多个实例之间的冲突。
虚基类是可以被实例化的。
66.C++哪些运算符不能被重载?
成员访问操作符,域解析操作符,条件运算符之类的不能重载。其中并不推荐对逗号运算符,逻辑或逻辑与之类运算符进行重载,容易造成歧义。
67.动态链接和静态链接的区别,动态链接的原理是什么?
区别:他们的最大区别就是在于链接的时机不同,静态链接是在形成可执行程序前,而动态链接的进行则是程序执行时。
静态库:就是将库中的代码包含到自己的程序之中,每个程序链接静态库后,都会包含一份独立的代码,当程序运行起来时,所有这些重复的代码都需要占用独立的存储空间,显然很浪费计算机资源。
动态库:不会将代码直接复制到自己程序中,只会留下调用接口,程序运行时再去将动态库加载到内存中,所有程序只会共享这一份动态库,因此动态库也被称为共享库。
动态链接原理:是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件
68.C++中怎么编译C语言代码?
使用extern“C”让C++代码按照C语言的方式去编译
69.未初始化的全局变量和初始化的全局变量放在哪里?
初始化的全局变量存放在数据段,数据段数据静态分配。
未初始化的全局变量存放在BSS(Block Started By Symbol)段,属于静态内存分配
70.说一下内联函数及其优缺点
内联函数是在编译期将函数体内嵌到程序之中,以此来节省函数调用的开销。
优点:是节省了函数调用的开销,让程序运行更加快速。
缺点:是如果函数体过长,频繁使用内联函数会导致代码编译膨胀问题。不能递归执行
顺便给大家分享一下,民族企业大厂前后端测试捞人,待遇给的还不错,感兴趣的可以来试试!
————————————————
原文链接:https://blog.csdn.net/songbijian/article/details/132507421
|
温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【 投诉建议】板块发帖举报。
|