面试速通宝典——18

299. 虚函数和纯虚函数的区别

‌‌‌‌  虚函数是一个可以在派生类中被重写的成员函数,它允许多态行为。
‌‌‌‌  纯虚函数则是在基类中声明但没有给出定义的虚函数,用 =0 语法表示。

‌‌‌‌  一个包含纯虚函数的类是抽象类,不能实例化,而是要求派生类提供纯虚函数的实现。简单来说,虚函数允许被覆盖,纯虚函数必须被覆盖

300. 构造函数和析构函数的作用,对类的成员变量的初始化,放在类内和放在类开头类外有什么区别?

‌‌‌‌  构造函数的作用是初始化类的对象。当一个对象被创建时,构造函数会被调用来为成员变量赋初始值,并执行任何必要的设置或分配资源的操作。

‌‌‌‌  析构函数则是在对象生命周期结束时被调用,用于执行清理工作,如释放分配的资源,他帮助防止资源泄露。

‌‌‌‌  对于类的成员变量初始化,如果在类内进行初始化,那么提供的是默认值,适用于所有未明确覆盖这些默认值的对象。如果在类的构造函数初始化列表中初始化,这是针对特定对象的初始化操作,可以基于构造函数接收的参数来设置成员变量的值。

‌‌‌‌  初始化列表比在构造函数体内赋值更有效,因为它可以直接构造成员变量,而不是先构造然后赋值,这对于对象成员和const或引用成员尤其重要,因为他们必须在初始化列表中初始化

301. 有没有遇到过opencv库底部出错的现象

OpenCV库底部出错的现象原因可能包括:

  1. API使用不当:比如错误的参数,不恰当的资源管理。
  2. 兼容性问题:库版本和依赖的操作系统或其他库版本不兼容。
  3. 资源限制:如内存不足,导致无法正常加载或处理数据。
  4. 内部库的bug:即使是广泛使用的库,也可能存在尚未修复的错误。
  5. 不支持的操作:尝试执行库不支持的功能或操作。

302. 栈区和堆区的区别

‌‌‌‌  栈区:是由操作系统自动管理、分配释放的内存区域,主要用于存放函数的局部变量、函数参数和函数调用的相关信息。栈上分配的内存有自动的作用域,当函数调用结束时,这部分内存会自动释放。

‌‌‌‌  堆区:是由程序员通过代码申请分配释放的内存区域,主要用于动态分配内存分配。堆上分配的内存生命周期是由程序员控制,如果不及时释放,可能会导致内存泄漏。堆的使用相对灵活,可以动态的分配大块内存。

303. 内存泄露的话,如何调试解决?

内存泄漏的调试解决可以通过以下步骤:

  1. 代码审查:检查代码中是否i有未配对的内存分配和释放。
  2. 使用调试工具:如Valgrind、Leaks(macOS)、Visual Leak Detector(Windows)来检测运行时内存使用情况。
  3. 分析堆栈跟踪:定位分配内存时函数调用堆栈,了解哪些分配未释放。
  4. 检查第三方库:确认是否有来自外部库的内存泄漏。

304. 有没有使用互斥锁,遇到死锁的问题,如何解决一个线程长时间占用资源,另外一个占用不到的情况?

死锁形成的四个必要条件:

  1. 互斥条件:资源同时只能由一个线程占用。
  2. 持有并等待:线程已持有资源,在等待获取其他资源时不释放已持有的资源。
  3. 不可抢占:资源不能被强制从占有线程取走,只能由持有线程主动释放。
  4. 循环等待:存在一组等待过程,其中每个线程持有的资源被下一个线程所请求.

针对一个线程长时间占用资源的问题,可以考虑:

  1. 确保占用锁的线程在完成其需要的操作后尽快释放锁
  2. 使用条件变量或者信号量来合理的调度线程,防止某个线程长时间占用资源
  3. 对长时间执行的任务拆分,减少单次锁定时间,为其他线程释放机会

305. Redis的数据类型

  1. 字符串(String):可以包含任何数据,如数字或文本。
  2. 哈希(Hash):键值对集合,适合存储对象。
  3. 列表(List):有序集合,可以添加或删除元素的序列。
  4. 集合(Set):不重复元素的无序集合。
  5. 有序集合(Sorted Set):不重复元素的集合,每个元素关联一个全重,元素按权重有序排列。
  6. 位图(Bitmap):通过位操作处理的字符串。
  7. HyperLogLogs:一种用来做基数统计的数据结构,如计算唯一值数量。
  8. 地理空间(Geo):用来存储地理位置信息并执行范围查询的数据类型。
  9. 流(Streams):用于存储一系列消息,适合消息队列和日志应用。

306. 哈希类型的应用场景?

  1. 存储用户信息,如用户名、密码、邮箱等。
  2. 缓存内容中的结构化数据,比如网页中的用户个人资料。
  3. 存储对象属性和其对应值
  4. 实现购物车功能,以用户ID为键,商品和数量为值。
  5. 维护多个计数器,如网站页面的点击数、产品评分等。

307. Redis的哈希类型有什么好处?

  1. 内存高效:使用哈希类型存储小对象可以节省内存。
  2. 便于操作:可以一次性读写多个字段,方便对对象的操作。
  3. 数据分组:哈希类型允许将相关的数据字段组织在一起,提高数据的整理性和可读性。

解释

  1. 内存高效

    • 解释:Redis哈希类型在存储小对象时特别高效。当哈希类型的键值对数量较少、值又比较小(比如是小字符串)时,Redis能采用一种紧凑的内部编码方式来存储这些数据。这样可以很大程度上节省内存。
    • 理解:假设你有一个用户对象,其中包含用户名、邮箱、年龄等信息。如果你用哈希类型来存储这些信息,Redis可以比用多个单独的键值对更高效地利用内存。
  2. 便于操作

    • 解释:Redis提供了多种操作哈希类型的方法,你可以一次性读取或写入多个字段。这大大简化了代码,减少了网络延迟。
    • 理解:比如,你可以用一个命令HMSET来同时将多个字段和值写入到一个哈希类型里,或者用HMGET一次性读取多个字段的值。这在需要对多个相关字段进行批量操作时非常方便,避免了多次网络往返开销。
  3. 数据分组

    • 解释:哈希类型允许你将相关的数据字段组织在一起。一个哈希可以看作是一个对象或者一个记录,它把多个相关的字段打包在一起。
    • 理解:把用户数据存储在哈希类型中,你可以有一个哈希KEY user:1001,里面包含多个字段如nameemailage。这样的话,所有与用户1001相关的信息都被组织在一起,数据结构一目了然,方便管理和使用。

总结理解:
‌‌‌‌  使用Redis哈希类型存储相关的小对象数据,可以在节省内存、减少操作复杂度和提高数据组织性这几个方面显著提升Redis系统的效率和易用性。利用哈希类型,你能更高效地管理和操作这些成组的相关数据。比如,对一个用户对象的操作可以归于一个哈希键,所有的相关字段都在一个地方,这让数据在逻辑上清晰明了,还能减少系统资源的浪费和多次数据操作的开销。

308. 哈希类型牺牲了什么?(缺点)

哈希类型牺牲了以下几点:

  1. 键空间:每个字段都存在于局部键空间中,不可用于全局查询。
  2. 数据结构复杂性:相比基本数据类型,哈希需要管理字段名和值,增加处理复杂性。
  3. 细粒度操作限制:与字符串类型相比,哈希类型不支持像“追加”这样的细粒度操作。

309. json的序列化和反序列化

‌‌‌‌  JSON的序列化是将数据结构或对象转换成JSON格式的字符串的过程。反序列化是将JSON格式的字符串转换回原始数据结构或对象的过程。这两个过程允许数据在不同的系统或程序之间以文本的形式安全地传输和存储

310. 使用JSON进行通信的好处

  1. 轻量级:JSON是轻量的数据交换格式
  2. 跨平台兼容:它被广泛支持,可在不同的编程语言和平台中使用。
  3. 易读易写:其格式清晰,便于阅读和编写。

311. POP3和IMAP的区别

POP3和IMAP是电子邮件获取的两种协议,他们的主要区别是:

  1. 邮件存储:POP3通常将邮件下载到本地客户端,并且可能会从服务器上删除,而IMAP则在服务器上保存邮件的副本,支持在多个设备上同步邮件。
  2. 多设备访问:IMAP更适合多设备访问和管理邮件,因为他在服务器上保留信息和邮件的状态(如读/未读,标记等)。
  3. 占用空间:POP3可能会节省服务器空间,因为邮件可以被下载并删除,IMAP则需要更多的服务器存储空间因为邮件保留在服务器上。
  4. 灵活性:IMAP提供了比POP3更高的灵活性,可以对邮件进行更复杂的操作,如搜索、文件夹管理等。

312. 知道bio/nio/aio/dio么?

  1. BIO(Blocking I/O):同步阻塞I/O,应用程序在执行I/O操作的时候会被阻塞,直到I/O操作完成。
  2. NIO(Non-blocking I/O):同步非阻塞I/O,应用程序执行I/O操作时不会被阻塞,可以立即返回继续执行其他任务,但需要不断地查询I/O操作是否完成,也称为轮询。
  3. AIO(Asynchronous I/O):异步I/O,应用程序发起I/O的操作后可立即返回执行其他任务,当I/O操作完成时,会收到通知或调用预设的回调函数。
  4. DIO(Direct I/O):直接I/0,绕过操作系统的缓存,直接从磁盘读写数据,通常用于需要高性能的场景。

313. static关键字的作用

  1. 静态局部变量:在函数内声明的static变量,该变量只初始化一次,并在函数调用之间保持其值。
  2. 静态类成员变量:在类定义中声明的static变量,该变量为类的所有对象共享,不属于任何单个实例。
  3. 静态类成员函数:在类定义中声明的static函数,该函数不需要通过对象来调用,也无法访问类的非静态成员。
  4. 静态全局变量:在文件作用域内声明的static变量,其作用域限制在声明它的文件内,其它文件不能访问。
  5. 静态局部变量(在文件作用域内):在文件作用域内声明的static变量具有全局寿命,但其链接属性是内部的,意味着他只在定义它的文件内可见。

314. static底层怎么实现让其他文件无法访问

‌‌‌‌  在底层实现中,当一个全局变量或函数前加上static关键字时,编译器会给这个符号分配“内部链接”属性。这意味着该符号的名字在其定义的翻译单元(通常是一个源文件)之外是不可见的,从而其他的文件或翻译单元无法通过该名字访问到这个符号链接器在处理不同的翻译单元时不会将这类具有内部链接属性的符号进行外部链。这就实现了static关键字限制访问范围的功能。

315. 对多态的理解

多态是面向对象编程的一个核心概念,它允许不同的对象对同一消息作出响应。在C++中,多态主要通过虚函数实现,他有两种形式:

  1. 编译时多态(静态多态):通过函数重载和操作符重载实现,编译器根据函数签名或操作符的不同,选择调用哪个特定的函数。
  2. 运行时多态(动态多态):通过虚函数和继承实现。基类声明虚函数,派生类可重写这些虚函数。调用哪个重写的方法由对象的实际类型决定,这个决定是在运行时做出的。这使得代码更加的灵活和可扩展。

316. 有没有除了虚函数之外的多态形式

‌‌‌‌  模板的多态,通常称为参数多态或编译时多态

317. 重载的理解

‌‌‌‌  重载是指在同一作用域存在多个同名的函数,但这些函数的参数类型、个数或顺序至少有一项不同。编译器根据函数调用时提供的参数来决定调用哪个函数。在C++中,可以重载函数和操作符,重载使得函数名可以根据不同的参数执行不同的任务,提高了代码的可读性和重用性。

318. 重载在编译之后怎么知道用的是哪个函数

‌‌‌‌  在编译时,编译器根据每个重载函数的参数列表对函数名进行名称修饰,生成独一无二的函数标识符。这个过程称为名称重整。因此,即使多个函数具有相同的基本名称,编译后他们也会有唯一的标识符。函数调用时,编译器根据传递的参数类型和数量,解析到对应的具有正确签名的函数。

319. 动态链接和静态链接的区别

‌‌‌‌  静态链接是指在编译时将所有用到的库函数的代码复制到最终的可执行文件中形成一个独立的二进制文件。而动态链接是指在程序运行时才从共享库中加载函数代码共享库不会被复制到可执行文件中。静态链接生成的文件体积较大,但是不依赖外部库;动态链接生成的文件体积较小,运行时需要确保相应的库在系统中可用。

320. 动态链接是怎么在链接库中找到需要的函数的

‌‌‌‌  动态链接使用动态链接器根据程序中未解析的符号和库名到动态链接库文件中查询符号表从而找到需要的函数的具体地址并进行地址绑定完成函数调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值