当前位置: 首页 > article >正文

C++面试速通宝典——22

396. C++如何调用C函数?

确保C函数的声明被放置在 extern “C” 的代码块中,这样可以告诉C++编译器这些函数按照C语言的方式进行链接。
在这里插入图片描述

正常调用C函数,就像调用C++函数一样。
![[images/Pasted image 20240806165800.png]]

‌‌‌‌  使用extern "C"防止C++编译器改变函数名(即名称修饰),这样链接器就能正确识别和链接C函数。

397. 字节对齐的概念和意义

字节对齐是计算机内存管理中的一种策略,它要求数据的起始地址按照某个数的倍数进行对齐

实现数字对其的意义有两点:

  1. 更快的读取速度:在许多系统中,如果数据落在自然边界上(即地址是某个值(4或8)的倍数),硬件可以在一个操作中取得数据。如果没有对齐,可能需要进行多次访问才能获取或存储同样的数据。
  2. 硬件要求:许多硬件平台只能在特定地址处访问特定类型的数据,对齐可以确保满足这些硬件平台的数据访问规定。例如,某些硬件平台不允许跨越字边界来存储数据,或者在这种系统中这样做会严重影响性能。

398. float变量如何和0比较

使用一个很小的正数作为容差来判断浮点数是否等于0。例如:
![[images/Pasted image 20240807144143.png]]
这种方法通过检查x是否在0的一个很小的区间来判断x是否等于0.

399. 协程算是异步吗?

‌‌‌‌  协程是一种异步编程的模型。协程允许异步执行操作如输入输出操作、耗时计算等,而不会阻塞程序的执行。这样,可以在一个线程内实现多个操作的并发执行,提高程序的效率和响应速度。

解释

  1. “协程是一种异步编程的模型。”

    • 协程(Coroutine)是一种实现异步编程的技术。与传统的同步编程相比,异步编程允许程序在等待某些操作完成(如I/O操作)时,继续执行其他任务。
  2. “协程允许异步执行操作如输入输出操作、耗时计算等,而不会阻塞程序的执行。”

    • 在传统的同步编程中,当执行一个耗时操作(例如读取文件、网络请求等)时,程序会被阻塞,必须等待操作完成才能继续执行后续代码。
    • 使用协程,可以在这些耗时操作期间,暂停当前协程的执行,允许其他协程运行。这意味着程序不会因为某个耗时操作而被完全阻塞,从而提高效率。
  3. “这样,可以在一个线程内实现多个操作的并发执行,提高程序的效率和响应速度。”

    • 协程在同一个线程内通过协作方式进行多任务处理。与多线程不同,协程之间切换的开销更小,因为它们共享相同的线程资源,不需要进行线程上下文切换。
    • 这使得在一个线程内可以并发执行多个操作,提高了程序的效率和响应速度。

示例解释

假设我们有一个读取多个文件内容的任务,使用同步编程和协程编程的区别如下:

同步编程:
def read_files_sync(file_list):
    for file in file_list:
        with open(file, 'r') as f:
            data = f.read()
            process(data)  # 处理数据

# 执行
read_files_sync(['file1.txt', 'file2.txt', 'file3.txt'])

在同步编程中,程序读取每个文件时会被阻塞,必须等待文件读取完成后,才能继续读取下一个文件。

协程编程(异步):
import asyncio

async def read_file_async(file):
    async with aiofiles.open(file, 'r') as f:
        data = await f.read()
        process(data)  # 处理数据

async def read_files_async(file_list):
    tasks = [read_file_async(file) for file in file_list]
    await asyncio.gather(*tasks)

# 执行
asyncio.run(read_files_async(['file1.txt', 'file2.txt', 'file3.txt']))

‌‌‌‌  在协程编程中,程序可以在等待文件读取的同时,执行其他文件的读取操作。这种方式不会阻塞程序的执行,使得文件读取任务可以并发进行,提高了程序的响应速度和效率。

总结

  • 协程 允许在单线程中实现异步操作,不会阻塞程序的执行。
  • 异步编程 使用协程可以在一个线程内并发执行多个任务,提高效率和响应速度。
  • 实质上,协程是通过在耗时操作时暂停当前协程,并允许其他协程执行,从而实现异步和并发。

400. unity协程是在主线程还是在子线程?靠什么调度的?

‌‌‌‌  unity中的协程运行在主线程,他们由unity的游戏循环调度。协程通过使用yield语句暂停执行,并将控制权返回给游戏循环,随后在合适的时机继续从暂停的地方继续执行。这允许进行延时操作和等待unity的其他事件,而不会阻塞主线程。

401. gameobject 上面的协程什么时候销毁?

Gameobject上面的协程会在该gameobject被销毁时结束。

403. 什么是虚函数?

‌‌‌‌  虚函数是在基类中使用关键字virtual声明的函数,它允许在派生类中被重写,以实现多态性。这意味着当你通过基类指针或引用调用一个虚函数时,实际调用的是对象的动态类型(派生类类型)中对应的函数实现,而非指针或引用的静态类型(基类类型)中的实现。这个机制允许在运行时根据对象的实际调用类型调用正确的函数版本,从而实现运行时的多态

404. 操作系统的段和页

  1. :段是一种逻辑地址空间的划分方式,以便将程序分成多个相对独立的部分,例如代码段、数据段等。每个段在逻辑内存中是连续的,但在物理内存中可能不连续。段的大小不固定,由程序所需要的内存量决定
  2. :页是一种物理地址空间的划分方式,将物理内存和逻辑内存都分割成固定大小的块。物理内存的页被称为页框,逻辑内存的页被称为页。通过页表,操作系统可以讲逻辑内存的页映射到物理内存的页框,实现内存的虚拟化。

段和页的主要区别在于:段是以逻辑的方式进行内存划分。

405. MySQL中什么是索引?

‌‌‌‌  索引是一种数据结构,用于提高数据检索效率,类似于书的目录,可以快速定位到数据的位置。

406. 建立索引的原则是什么?

  1. 选择性高的字段:字段的唯一值越多,索引的效果越好。高选择性意味着查询可以从大量数据中快速过滤出少量结果。
  2. 常用作查询条件的字段:经常出现在WHERE子句中的字段是建立索引的好候选。
  3. 排序、分组字段:经常用于ORDER BY、GROUP BY子句的字段,建立索引可以提高排序和分组的效率。
  4. 连接字段:在多表JOIN操作中作为连接条件的字段,索引可以显著加快连接查询的速度。
  5. 避免过宽的字段:过宽的字段意味着索引空间更大,维护成本更高,应优先考虑短索引。
  6. 避免频繁修改的字段:字段数据频繁变动会导致索引频繁重建,影响性能。
  7. 考虑创建组合索引:多个字段经常一起作为查询条件时,考虑创建组合索引,但需注意字段顺序。
  8. 权衡索引成本:虽然索引可以提高查询效率,但也会增加写操作(INSERT、UPDATE、DELETE)的成本和占用额外的存储空间。合理构建和维护索引以平衡这种权衡。

407. 索引是怎么是实现的?

索引通常通过数据结构如B树(尤其是B+树)和哈希表实现的。

408. 讲讲为什么使用B+树?

  1. B+树是一种平衡多叉树,保证了所有叶子节点都在同一层,查询路径长度一致,确保了查询性能的稳定性。
  2. B+树的叶子节点按键值有序链接,便于实现范围查询。
  3. 相对于二叉树等其他平衡树,B+树有更高的分支因子,减少了磁盘I/O的操作次数。
  4. B+树的设计充分利用了磁盘预读原理,减少了页的分裂概率,提高了空间和时间的局部性。
  5. B+树只在叶子节点保存数据的指针或实际数据,在内部节点仅存储键值,提高了节点存储效率。

解释

1. B+树是一种平衡多叉树,保证了所有叶子节点都在同一层,查询路径长度一致,确保了查询性能的稳定性。

  • 平衡多叉树:B+树是一种每个节点可以有多个子节点的树结构,所有路径长度一致,保证了查询性能稳定。
  • 一致路径长度:所有叶子节点都在同一层,因此从根到叶子节点的路径长度相同,避免了不平衡树带来的查询效率问题。

2. B+树的叶子节点按键值有序链接,便于实现范围查询。

  • 有序链接:叶子节点按键值顺序排列,并通过链表连接起来。
  • 范围查询:通过遍历有序链表,可以高效地实现范围查询,快速找到并返回范围内的所有数据。

3. 相对于二叉树等其他平衡树,B+树有更高的分支因子,减少了磁盘I/O的操作次数。

  • 更高的分支因子:每个节点可以有多个子节点,分支因子大。
  • 减少磁盘I/O:每个节点存储更多的键和指针,减少了需要访问的节点数量,从而减少磁盘I/O操作,提高查询效率。

4. B+树的设计充分利用了磁盘预读原理,减少了页的分裂概率,提高了空间和时间的局部性。

  • 磁盘预读:磁盘通常按页读取数据,B+树的节点大小可以与磁盘页大小匹配,利用预读减少多次I/O操作。
  • 减少页分裂:节点有较大容量,可以减少频繁的分裂操作。
  • 局部性:数据按顺序存储,提高了访问的空间和时间局部性。

5. B+树只在叶子节点保存数据的指针或实际数据,在内部节点仅存储键值,提高了节点存储效率。

  • 叶子节点:存储实际数据或数据指针,数据访问集中在叶子节点。
  • 内部节点:仅存储键值和指针,用于快速定位数据所在的叶子节点。
  • 存储效率:减少了内部节点的大小,使得更多的节点可以加载到内存中,提高了存储和查询效率。

总结

B+树的这些特性使它特别适用于需要高效读取、写入和范围查询的应用场景,如数据库和文件系统。具体来说:

  1. 查询稳定性:一致的查询路径长度带来稳定的查询性能。
  2. 范围查询:有序链接的叶子节点使得范围查询非常高效。
  3. 高效磁盘I/O:高分支因子和利用磁盘预读原理减少了磁盘I/O次数。
  4. 局部性:数据存储具有良好的空间和时间局部性,提高访问效率。
  5. 存储效率:内部节点只存储键值,优化了节点存储空间。

这些优点使得B+树在处理大规模数据时特别有效。

409. 什么是聚簇索引和非聚簇索引?

聚簇索引直接按照一定顺序存储数据记录的物理形式。一个表只能有一个聚簇索引,因为数据只能按照一种顺序排列。
非聚簇索引不改变数据实际存储顺序,而是创建一个单独的索引结构来指向数据记录的位置,一个表可以有多个非聚簇索引。

410. B+树是什么?

B+树是一种自平衡的树数据结构,他维护排序数据以允许搜索、顺序访问、插入和删除操作在对数时间内进行。B+树特别适合用于读写较大数据块的存储系统。主要特点包括:

  1. 所有的叶子节点都位于同一层,并且包含数据及其对应的键值。
  2. 所有的非叶子节点都可以作为索引部分,只包含其子节点中的最大(或最小)键值。
  3. 叶子节点通过指针相连,这为遍历提供了高效的顺序访问路径。

411. 什么叫慢查询?

‌‌‌‌  慢查询是指在数据库中执行时间过长,响应速度慢的查询操作。具体的时间阈值可以根据系统的具体需求进行定义。例如,如果一条查询语句执行时间超过了设定的阈值(比如1秒),那么就可以将这条查询语句标记为慢查询。慢查询的原因可能包括数据量过大、数据库设计不合理、索引问题等。了解和优化慢查询对于提升数据库和整个系统的性能有重要i作用。

412. 什么是事务?

‌‌‌‌  事务是数据库管理系统执行过程中的一个操作序列单元,它是一个不可分割的工作单位。事务是具备以下四个标准属性,通常被称为ACID属性:

  1. 原子性:事务内的所有操作要么全部成功,要么全部失败回滚。
  2. 一致性:事务必须保证数据库从一个一致性状态转移到另一个一致性状态。
  3. 隔离性:并发执行的事务之间要相互隔离,防止互相影响。
  4. 持久性:一旦事务提交,其结果就永久地保存在数据库中。

413. 讲讲什么是动态规划以及他的主要思想

动态规划(DP)是一种算法设计技术,主要用来解决特定类型的优化问题。它能够将复杂问题分解为更简单的子问题,并且存储这些子问题的解,避免了重复计算,极大地提高了计算效率

动态规划的主要思想基于两个核心要素:

  1. 最优子结构:关键在于识别出给定问题的解可以通过其子问题的最优解有效构造出来。换言之,原问题的最优解包含了其子问题的最优解,这样就可以逐步构建出整个该问题的最优解。
  2. 重叠子问题:动态规划适用于子问题重叠的情况,即不同的问题部分包含了相同的子问题。为了提高效率,动态规划会保存这些子问题的解,这样当再次遇到相同的子问题时,就可以直接使用已经计算过的结果。

以下是实施动态规划的步骤:

  1. 定义状态:分析问题性质,定义适合的状态表示解的各个方面。
  2. 状态转移方程:根据问题的规则,确定状态之间的转移方程,这是动态规划的核心部分。
  3. 初始化条件:确定初始状态值,以正确开始状态转移的过程。
  4. 计算顺序:确定计算状态值的顺序,通常是一种基于之前计算结果的迭代过程。
  5. 构造最优解:利用计算出的状态值构造问题的最终解。

414. 动态规划一般可以解决什么样子的实际问题?

  1. 计算最优解:比如路径寻找(最短路径问题)、资源分配(背包问题)。
  2. 决策制定:如工程项目的调度、库存管理。
  3. 序列:比如字符串比对(编辑距离问题)、最长递增子序列。
  4. 组合:比如子集划分(划分问题)、不同路径的计算问题。

415. 最长公共子序列,只用说思路,然后问最长公共子序列的现实价值

在C++中实现最长公共子序列(LCS)通常使用动态规划。创建一个二维数组dp,其中dp[i][j]代表第一个序列前 i 个元素和第二个序列前 j 个元素的LCS长度。遍历两个序列,当遇到相同元素时,dp [i-1][j-1] + 1 , 否则,dp[i][j] = max(dp[i-1][j] , dp[i][j-1])。最终,dp[m][n](m和n分别是两个序列的长度)即为所求的LCS长度。

最长公共子序列在实际中的应用包括:

  1. 在文本控制和代码审查中用来识别文件之间的差异
  2. 在数据对比和数据同步中确定相似度高的记录
  3. 在撤销功能的实现中记录和比较文本的历史更改

416. const常量和static变量在类里面的区别

  1. 存储访问:
    1. const常量是类的一个成员,它的值在编译时就已经确定,并且在类的每个对象在都有一份独立的拷贝。每个对象都不能修改他的const成员的值。
    2. static变量属于类本身,而不是属于类的某个对象。他在程序的生命周期内只有一份存储,被所有对象共享。static变量需要在类外进行定义和初始化。
  2. 初始化:
    1. const常量必须在声明时或者通过构造函数的初始化列表进行初始化
    2. static变量可以在类外初始化,且只能初始化一次
  3. 作用和用途:
    1. const常量通常用于定义类中的不可变数据,例如物理常数、配置值等。
    2. static变量常用于所有对象间共享数据,或者计数类实例数量、实现单例模式等。
  4. 使用场景举例:
    1. 假设有一个circle类,其中有一个const成员PI(圆周率),他表示一个常量值3.1415926,每个Circle对象访问的PI都是一样的,但他属于每个对象的一部分。
    2. 如果在Circle中定义一个static int count;变量用以记录创建的Circle对象数量,那么所有的Circle对象都将共享这个count变量,而且它不属于任何一个Circle对象,而是属于Circle类。
  5. 语法:
    1. 示例const常量使用:在类定义内class Myclass{const int myCount = 5;};
    2. 示例static变量定义和初始化:在类内声明static int myStaticVar;,在类外初始化int MyClass::myStaticVar = 0;

417. static修饰类函数访问成员的限制

‌‌‌‌  当函数被声明为static时,它可以直接通过类来调用,而无需创建类的对象实例。这就意味着static成员函数只能访问类的static成员(变量或函数),他们不能访问类的非static成员。这是因为非static成员属于类的实例,而static成员函数在没有任何对象实例的情况下也能被调用

  1. 不能访问非static成员:static成员函数不能直接访问非static成员变量和非static成员函数,因为这些成员要求有一个具体的对象实例才能被访问。
  2. 不能使用this指针:static成员函数不接受this指针,因为this指针指向类的某个具体实例,而static成员函数与具体实例无关。
  3. 可以访问static成员:static成员函数可以访问类的其他static成员变量和static成员函数,因为这些成员不依赖于类的实例。
  4. 可以被正常函数调用:一个类的static成员函数可以被该类的非static成员函数调用,也可以被其它类和非类(全局)函数调用,因为他们的访问不受限于对象实例。
  5. 使用场景:static成员函数通常用于执行不依赖于对象状态的操作,例如工具函数,或者类级别的行为(例如工厂模式中的工厂方法)。

418. 内联和普通函数的区别

‌‌‌‌  内联函数会在编译时将函数体嵌入到每个调用点,以减少函数调用的开销;而普通函数则通过常规调用机制执行,涉及跳转和返回操作。

‌‌‌‌  内联函数可减少调用成本,但可能增加代码体积;普通函数调用清晰但开销相对较大。内联是编译器的建议,具体内联与否取决于编译器决策。

419. 计算结构体大小需要注意什么?

  1. 成员大小:每个成员的数据类型决定了其大小。
  2. 对齐/Padding:为了保证内存访问的效率,编译器会根据硬件平台的要求自动添加填充字节(padding)以对其成员。
  3. 对齐规则
    1. 结构体的总大小是最宽基本类型成员的整数倍。
    2. 每个成员的偏移量(从结构体开始的位置)是该成员类型大小的整数倍。
  4. 继承:如果结构体是从另一个结构体继承而来,基类的大小也需要考虑在内。
  5. 位字段:位字段成员可能会使大小计算更加复杂,因为它们可以使得成员在不足一个字节的尺寸内打包。
  6. 虚函数:如果结构体中有虚函数,则需要考虑虚函数表的指针大小。
  7. 编译器选项:编译器的某些选项(如pack)可以改变默认的对齐方式。
  8. 平台和编译器:不同的编译器或目标平台可能有不同的对其需求。

http://www.kler.cn/news/342771.html

相关文章:

  • github 国内文件加速下载
  • 黑马JavaWeb开发跟学(九)MyBatis基础操作
  • 机器学习【医疗领域及其药品搭建】
  • 倪师学习笔记-天纪-斗数简介
  • Vue】Vue扫盲(四)组件化思想与简单应用
  • 无人驾驶打造“新丝路”,驭势科技在卡塔尔设立研发运营中心
  • 318页PPT5G智慧校园顶层设计方案
  • Spring Boot 事务管理入门
  • 深度学习--------------------------------使用注意力机制的seq2seq
  • 服装生产管理:SpringBoot框架的高效策略
  • [git] github管理项目之环境依赖管理
  • 数据结构前置知识(下)
  • java-07 多线程-并发编程(线程池,线程状态)
  • 程序设计基础I-实验7 函数(编程题)
  • 邮件营销与社交媒体结合:打造全方位营销!
  • ESP8266模块(WIFI STM32)
  • 数据结构之二叉搜索树(key模型与key_value模型)
  • 使用OpenFeing远程调用时为方法添加请求头
  • 掌握 C# 设计模式:从基础到依赖注入
  • Django学习笔记七:用户认证与授权