主题:2024最新大厂C++面试真题合集,大厂面试百日冲刺 day9
腾讯实习
指针常量和常量指针
常量指针(const Type* ptr):指针指向的内容不能被改变,但指针本身可以改变指向。
指针常量(Type* const ptr):指针自身的值即内存地址不能改变,但指向的内存内容可以被改变。
int x/8性能优化
使用位运算进行性能优化,可以将 int x/8 替换为 x >> 3,这样利用位移操作来代替除法运算。
介绍虚函数及其用法
虚函数是一个在基类中声明为virtual的函数,它可以在派生类中被重写,以实现多态。当通过基类的指针或引用调用一个虚函数时,会根据对象的实际类型来调用对应的函数实现,这个过程称为动态绑定。
为什么构造函数不能是虚函数
构造函数不能被声明为虚函数,因为虚函数依赖于对象的虚函数表来实现动态绑定,但是当构造函数被调用时,对象正在被构建,虚函数表尚未建立,因此无法调用。另外,构造函数的任务是初始化对象的状态,而多态是针对已经初始化的对象进行操作的概念,因此将构造函数设为虚函数也没有意义。
虚函数表占几个字节
虚函数表的大小取决于编译器的实现和类的设计。在一般情况下,一个类如果包含虚函数或者继承了有虚函数的父类,编译器会为该类的每个对象添加一个虚函数表指针。在大多数32位系统上,一个指针的大小是4字节;在64位系统上,一个指针的大小是8字节。
虚函数表本身是一个指针数组,其大小等于虚函数数量乘以指针的大小。
指针和引用的区别
-
存储和使用:指针是一个变量,存储的是一个地址,可以被重新赋值和修改;引用是一个已存在变量的别名,初始化后就不能重新绑定。
-
空值:指针可以是nullptr,引用必须绑定到一个合法的对象。
-
操作符:指针需要解引用操作符 * 来访问目标对象,引用直接访问。
-
地址获取:可以使用 & 来获取指针指向的内存地址,对于引用,&得到的是引用所绑定对象的地址。
-
指针可以有多级(如双指针、三指针等),但是没有“多级引用”。
-
C++中构造和析构函数的形参通常使用引用,以避免对象的复制。特别是对拷贝构造函数和赋值操作符,其形参必须是引用。而普通的函数则可以根据需要选择使用指针或引用。
c++面向对象三大特征
封装、继承、多态
vector和quene区别
vector是一个动态数组,支持随机访问,可以在任何位置插入和删除元素,但效率较低(尤其是在头部)。
queue是一个先入先出(FIFO)的数据结构,只能在队尾插入,在队首删除。
vector对于随机访问有很高的效率,但在头部或中间插入和删除元素的效率较低。
queue在其两端操作(入队和出队)具有较高的效率,但不支持随机访问。
https和http区别
-
安全性:HTTPS提供了加密传输和身份验证,保障数据在传输过程中的安全性,而HTTP传输的数据是未加密的,容易被第三方窃取或篡改。
-
端口:HTTPS默认使用443端口,HTTP默认使用80端口。
-
性能:由于HTTPS在传输数据前需要进行加密,可能会略微影响传输效率。然而,随着技术发展,这种影响正在减小。
https如何实现加密/解密
HTTPS通过SSL/TLS协议实现数据的加密和解密。具体运作过程如下:
-
密钥交换:客户端和服务器之间通过安全握手协议(Secure Sockets Layer Handshake Protocol)交换加密算法和会话密钥。
-
数据加密:通过交换的会话密钥,服务器和客户端将通信内容进行加密,确保数据的隐私性。
-
数据解密:收到加密数据的一方使用会话密钥对数据进行解密,获取原始信息。
-
数据完整性:通过消息完整性检查,验证数据是否在传输过程中被篡改。
数字证书什么作用
-
身份验证:证明服务器的身份,避免用户连接到伪装的站点。
-
加密传输:提供公钥,以供客户端和服务器之间建立安全的加密通信。
-
数据完整性:确保传输的数据没有被篡改。
如果没有被授权的证书如何通过验证
-
自签名证书:用户可以创建自己的证书,并手动将它添加到信任的证书列表中。但是,这种方式的显著缺点是,在不同设备或用户之间同步信任列表可能会很困难。
-
忽略证书错误:在一些应用中,可以设置成忽略掉SSL/TLS的证书错误。但这样做将严重降低了网络安全性,使得中间人攻击成为可能,因此在实际操作中要小心使用。
如何解决线程竞争
解决线程竞争可以通过以下方法:
-
互斥锁(Mutex):确保同一时间内只有一个线程可以访问共享资源。
-
读写锁(Read-Write Lock):允许多个线程读共享资源,但写操作是互斥的。
-
原子操作:使用原子操作直接对数据进行操作,确保操作的原子性。
-
信号量(Semaphore):通过计数信号量控制同时访问资源的线程数。
-
条件变量(Condition Variable):允许线程在特定条件下等待或发送通知,以避免竞争。
锁分类有几种方式
按照功能分类:
-
互斥锁(Mutex)
-
读写锁(Read/Write Locks)
-
递归锁(Recursive Locks)
按照实现机制分类:
-
自旋锁(Spinlock)
-
阻塞锁(Blocking Lock)
-
乐观锁/悲观锁
按照作用范围分类:
-
全局锁
-
细粒度锁
特殊类型的锁:
-
条件变量(Condition Variables)
-
信号量(Semaphore)
-
读写分离锁(Read-Write Lock)
怎么查找函数位置有什么区别
查找函数的位置可以通过以下方式:
-
阅读文档:最直接的查找函数位置的方法是查看其官方文档或参考手册。
-
使用IDE:集成开发环境(IDE)通常有内置的搜索功能,可快速找到函数定义。
-
使用grep:在Linux环境中,可以使用grep工具在文件中搜索文本模式。
-
使用代码索引工具:如ctags或Source Insight,这些工具可以在大型项目中快速定位函数定义。
多线程编程过程
多线程编程过程通常包括以下步骤:
-
创建线程:确定需要多线程执行的任务,并使用相应的API创建线程。
-
定义线程任务:编写执行线程功能的代码块,定义线程开始执行时要调用的函数或方法。
-
启动线程:初始化线程并开始执行定义的任务。
-
线程同步:使用互斥锁、信号量等机制同步多个线程间的操作,避免数据冲突。
-
管理线程生命周期:监控线程的执行状态,实现线程的暂停、继续和停止等控制。
-
线程通信:通过共享内存、消息队列等方式实现线程间的数据交换和通信。
-
回收资源:线程任务完成后,回收线程所占用的资源。
tcp三次握手
TCP 的三次握手指的是建立一个 TCP 连接时需要经过的三个步骤:
-
SYN:客户端发送一个 SYN(同步)包给服务器,请求建立连接,同时发送自己的初始序列号。
-
SYN-ACK:服务器收到 SYN 包后,向客户端发送一个 SYN-ACK(同步应答)包,确认收到了 SYN 包,同时也发送自己的初始序列号。
-
ACK:客户端收到 SYN-ACK 包后,再发送一个 ACK(应答)包给服务器,确认收到了服务器的 SYN-ACK 包。至此,连接建立完成。
最后顺便给大家分享一下,民族企业大厂前后端测试捞人,待遇给的还不错,感兴趣的可以来试试!