实习面试记录

湖南某操作系统中厂(9月)

首先是科研项目相关的问题,然后是其他问题如下:

STL中,vector,map和unorded_map底层是怎么实现的?

在C++标准库中,vector和map都是基于模板类实现的容器。

  1. vector底层实现:
    vector是一个动态数组,它在内存中以连续的块存储元素。当需要添加或删除元素时,vector会根据需要自动重新分配内存空间,以保持元素的连续存储。通常情况下,vector会分配比实际需求大一些的内存空间,以避免频繁的重新分配开销。

  2. map底层实现:
    map是一个键-值对的关联容器,底层使用红黑树(Red-Black Tree)实现。红黑树是一种自平衡二叉搜索树,它具有良好的查找、插入和删除性能。红黑树保持了以下性质:节点要么为红色,要么为黑色;树的根节点和叶子节点(空节点,即NULL)为黑色;如果一个节点是红色的,那么它的子节点必定是黑色的;对于任意节点,其到达其所有后代叶子节点的路径上,黑色节点的数量相同。

STL中,map和unorded_map底层是怎么实现的?区别?

在STL(Standard Template Library)中,map和unordered_map都是关联容器,用于存储键值对的数据结构。它们的底层实现方式不同。

  1. map底层实现:
    map使用红黑树(Red-Black Tree)实现,它是一种自平衡的二叉搜索树。红黑树具有以下性质:每个节点要么是红色,要么是黑色;根节点是黑色;叶子节点(空节点)是黑色;红色节点的两个子节点都是黑色;对于每个节点,从该节点到其所有后代叶子节点的简单路径上,包含相同数目的黑色节点。

  2. unordered_map底层实现:
    unordered_map使用哈希表(Hash Table)实现,也被称为散列表。哈希表通过将键映射到桶(bucket)来实现快速查找。键经过哈希函数计算得到一个索引,然后在该索引处的桶中查找或插入键值对。当多个键被哈希到同一个索引时,通常会使用链表、红黑树或其他方法来解决冲突。

总结起来,map使用红黑树实现,保证了元素的有序性,但查找速度较慢;unordered_map使用哈希表实现,查找速度较快,但元素的顺序是无序的。在使用时,可以根据具体的需求进行选择。

怎么把map清空,内存删除呢?

要清空一个 std::map 容器 ,你可以使用 clear() 函数。调用 clear() 函数会删除容器中的所有键值对,使其变为空容器。这只会清除容器中的数据,不会释放相应的内存。

以下是一个示例代码片段,展示了如何清空 std::map 容器:

std::map<KeyType, ValueType> myMap;// 添加键值对至 myMap// 清空容器
myMap.clear();

在调用 clear() 函数后,myMap 将变为空的 std::map 容器,其大小为0,不再包含任何键值对。

请注意,调用 clear() 函数只会删除容器中的数据,而不会直接释放内存。内存的释放是由容器的析构函数负责的,当容器本身被销毁时,与之关联的内存会被自动释放。如果你需要手动释放内存,可以通过销毁容器对象或将其重新赋值为一个新的空容器来实现。例如:

// 销毁容器,释放内存
myMap.~map();// 或者将其重新赋值为空容器
myMap = std::map<KeyType, ValueType>();

当使用这些方法时,之前 std::map 容器关联的内存将会被释放。使用哪种方法取决于你的具体需求和代码结构。

STL是线程安全的吗?

STL(Standard Template Library)是C++标准库的一部分,其中包含了众多的模板类和函数,用于实现各种数据结构和算法。STL本身并没有提供对多线程的直接支持,因此,并不能说STL是线程安全的。

在多线程环境中使用STL容器和算法时,需要开发人员自行确保线程安全性。多个线程同时访问和修改同一个STL容器的共享数据是一种典型的线程安全问题,如果不采取适当的措施,可能会导致数据竞争和不确定的行为。

为了在多线程环境中安全地使用STL,可以采取以下一些措施:

  1. 互斥锁(Mutex):使用互斥锁来保护访问和修改STL容器的临界区。在每次对STL容器进行读写操作之前,使用互斥锁进行加锁,在操作完成后再进行解锁。这样可以确保多个线程之间的互斥访问。

  2. 读写锁(Read-Write Lock):如果多个线程之间主要是读操作,可以考虑使用读写锁来提高性能。读写锁允许多个读操作同时进行,但会阻塞写操作。

  3. 原子操作(Atomic Operations):STL提供了一些原子操作类型,如std::atomic。原子操作是在单个指令中执行的,不能被中断,因此可以保证在多线程环境下的原子性访问。

  4. 线程安全的容器(Thread-Safe Containers):除了STL容器之外,一些第三方库或框架提供了线程安全的容器,如Intel TBB、Boost等。这些容器封装了线程安全性,可以更方便地在多线程环境中使用。

C++ 14才引入的线程安全吗

C++14并没有引入特定的机制来确保线程安全,但它引入了一些新的标准库组件,以支持多线程编程。这些组件包括std::thread、std::mutex、std::condition_variable等,它们是基于C++11引入的线程支持功能的进一步扩展。

C++11引入了原生的多线程支持,包括std::thread和std::mutex等,但在C++11中没有提供标准库实现的并发数据结构或其他专门用于线程安全的组件。这意味着,在C++11中,开发人员需要自行实现线程安全的代码,使用互斥锁、条件变量等机制来确保线程安全。

C++14在C++11的基础上提供了一些新的标准库组件,如std::shared_mutex、std::atomic_shared_ptr,它们提供了更方便的方式来实现线程安全。而且,C++14引入了一些语法上的改进,如lambda函数的改进、typedef的改进等,使得编写线程安全的代码更加简洁和方便。

总结起来,C++14并没有直接引入线程安全的概念或机制,但它提供了更丰富的标准库组件和语法上的改进,使得在C++中编写线程安全的代码更加便捷和易于理解。然而,确保线程安全仍然是开发人员的责任,需要正确地使用这些组件和机制。

python常见的数据结构,python中哪些数据结构是不可变的?

Python 提供了许多常见的数据结构,以下是一些常见的数据结构及其在 Python 中的表示:

  1. 列表(Lists):有序、可变的数据集合。

    • 示例:my_list = [1, 2, 3, 4, 5]
  2. 元组(Tuples):有序、不可变的数据集合。

    • 示例:my_tuple = (1, 2, 3, 4, 5)
  3. 字典(Dictionaries):存储键-值对的无序集合,通过键进行访问。

    • 示例:my_dict = {'name': 'John', 'age': 30, 'city': 'New York'}
  4. 集合(Sets):存储唯一元素的无序集合。

    • 示例:my_set = {1, 2, 3, 4, 5}
  5. 字符串(Strings):字符的有序集合。

    • 示例:my_string = "Hello, world!"
  6. 数组(Arrays):有序、可变的数据集合,需要导入 array 模块。

    • 示例:import array; my_array = array.array('i', [1, 2, 3, 4, 5])
  7. 堆(Heaps):优先级队列,需要导入 heapq 模块。

    • 示例:import heapq; my_heap = [3, 1, 4, 1, 5]; heapq.heapify(my_heap)
  8. 链表(Linked Lists):通过节点连接的线性数据结构,可以使用自定义类实现。

    • 示例:
      class Node:def __init__(self, data):self.data = dataself.next = None# 创建链表
      head = Node(1)
      second = Node(2)
      third = Node(3)head.next = second
      second.next = third
      

这只是 Python 中一些常见的数据结构示例,每个数据结构都有其特定的用途和操作。根据实际需求选择合适的数据结构,Python 提供的丰富的数据结构可以满足不同的编程任务。
在 Python 中,有以下几种不可变的数据结构:

  1. 数字类型(Number types):包括整数(int)、浮点数(float)、复数(complex)等。

    • 示例:x = 10
  2. 字符串(Strings):由单个字符组成的有序序列。

    • 示例:name = "Alice"
  3. 元组(Tuples):有序的对象序列,一旦创建就不能修改。

    • 示例:point = (3, 4)
  4. 冻结集合(Frozen Sets):不可变的集合对象。

    • 示例:my_set = frozenset([1, 2, 3])
  5. 字节串(Bytes):存储二进制数据的不可变序列。

    • 示例:data = b"Hello"

这些不可变的数据结构是指一旦创建就无法修改其内容,每次对其进行操作都会创建一个新的对象。这种不可变性有助于确保数据的一致性和安全性,并且使得这些数据结构可以作为字典的键或集合的元素使用。另外,对于数值计算和存储不变数据等场景,使用不可变数据结构也可以提高性能。

Linux常见的命令,Linux命令统计内存占用

以下是一些常见的 Linux 命令:

  1. 文件和目录操作:

    • ls: 列出目录内容。
    • cd: 切换目录。
    • pwd: 显示当前工作目录。
    • mkdir: 创建目录。
    • touch: 创建空文件或更新文件时间戳。
    • cp: 复制文件或目录。
    • mv: 移动或重命名文件或目录。
    • rm: 删除文件或目录。
    • find: 在文件系统中查找文件。
  2. 文件内容查看和编辑:

    • cat: 显示文件内容。
    • more: 分页显示文件内容。
    • less: 分页显示文件内容,支持向前和向后翻页。
    • head: 显示文件开头部分。
    • tail: 显示文件结尾部分。
    • grep: 在文件中查找匹配的文本。
    • vi / vim: 强大的文本编辑器。
  3. 系统信息查看:

    • df: 显示磁盘空间使用情况。
    • du: 显示目录或文件的磁盘使用情况。
    • top: 实时显示系统资源使用情况。
    • free: 显示系统内存使用情况。
    • uname: 显示系统信息(内核版本、操作系统等)。
    • ifconfig: 显示和配置网络接口信息。
  4. 系统管理和进程控制:

    • ps: 显示当前运行的进程。
    • kill: 终止指定进程。
    • shutdown: 关闭系统。
    • reboot: 重启系统。
    • service: 管理系统服务。
    • systemctl: 管理系统服务和日志。
    • sudo: 以超级用户权限运行命令。
  5. 压缩和解压缩:

    • tar: 打包和解包文件。
    • gzip: 压缩文件。
    • gunzip: 解压缩文件。
    • zip: 压缩文件和目录。
    • unzip: 解压缩 Zip 文件。

这只是一小部分常见的 Linux 命令,Linux 提供了丰富的命令行工具和实用程序,以满足各种需求。可以通过 man 命令来查看命令的帮助文档,了解更多详细信息。

python中的推导函数,List和set推导式的区别?

在 Python 中,有两种常见的推导函数,它们分别是列表推导式(List Comprehension)和集合推导式(Set Comprehension)。这些推导函数可以更简洁地创建列表和集合。

  1. 列表推导式(List Comprehension):
    列表推导式允许我们通过对一个可迭代对象中的每个元素应用一个表达式来创建一个新的列表。

例如,如果我们想创建一个包含 1 到 5 的平方的列表,可以使用以下列表推导式:

squares = [x**2 for x in range(1, 6)]
# 输出结果: [1, 4, 9, 16, 25]

列表推导式还可以包含条件语句,以过滤元素。例如,我们可以创建一个包含 1 到 10 中偶数的列表:

even_numbers = [x for x in range(1, 11) if x % 2 == 0]
# 输出结果: [2, 4, 6, 8, 10]
  1. 集合推导式(Set Comprehension):
    集合推导式与列表推导式类似,但创建的是一个集合而不是一个列表。它使用大括号 {} 来表示集合。

例如,我们可以使用集合推导式创建一个包含 1 到 5 的平方的集合:

squares = {x**2 for x in range(1, 6)}
# 输出结果: {1, 4, 9, 16, 25}

与列表推导式类似,集合推导式也可以包含条件语句。例如,我们可以创建一个包含 1 到 10 中偶数的集合:

even_numbers = {x for x in range(1, 11) if x % 2 == 0}
# 输出结果: {2, 4, 6, 8, 10}

这些推导函数提供了一种简洁而直观的方式来创建列表和集合,可以减少代码量并提高可读性。除了列表和集合推导式,Python 还支持字典推导式和生成器表达式等其他形式的推导函数。

在 Python 中,推导式是一种简洁的语法,可以通过对可迭代对象中的元素应用表达式和条件语句来创建新的数据结构。以下是 Python 中常见的推导式类型:

  1. 列表推导式(List Comprehension):
    列表推导式允许我们通过对一个可迭代对象中的每个元素应用一个表达式来创建一个新的列表。语法形式为:[expression for item in iterable if condition]

    示例:

    squares = [x**2 for x in range(1, 6)]
    # 输出结果: [1, 4, 9, 16, 25]
    
  2. 集合推导式(Set Comprehension):
    集合推导式与列表推导式类似,但创建的是一个集合而不是一个列表。语法形式为:{expression for item in iterable if condition}

    示例:

    squares = {x**2 for x in range(1, 6)}
    # 输出结果: {1, 4, 9, 16, 25}
    
  3. 字典推导式(Dictionary Comprehension):
    字典推导式允许我们通过对一个可迭代对象中的每个元素应用表达式来创建一个新的字典。语法形式为:{key_expression: value_expression for item in iterable if condition}

    示例:

    squares = {x: x**2 for x in range(1, 6)}
    # 输出结果: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    
  4. 生成器表达式(Generator Expression):
    生成器表达式可以看作是一个简化版的列表推导式,它返回一个生成器对象,而不是创建一个完整的列表。语法形式为:(expression for item in iterable if condition)

    示例:

    squares = (x**2 for x in range(1, 6))
    # 输出结果: <generator object <genexpr> at 0x10aeb0b50>
    

python中set传参和List传参有什么区别

在 Python 中,set 和 list 是常见的数据结构,它们在传参时有一些区别:

  1. 传参方式:

    • set:当你将一个 set 对象作为参数传递给函数时,实际上是将该 set 对象的引用传递给了函数。这意味着函数内部对传递的 set 对象进行的任何修改都会影响到原始的 set 对象。
    • list:与 set 不同,当你将一个 list 对象作为参数传递给函数时,也是将该 list 对象的引用传递给了函数。也就是说,函数内部对传递的 list 对象的修改也会影响到原始的 list 对象。
  2. 可变性:

    • set:set 是可变的数据类型,意味着你可以对其进行添加、删除、更新等操作,而不会创建一个新的 set 对象。因此,如果在函数内部修改了传递的 set 对象,原始的 set 对象也会被修改。
    • list:list 也是可变的数据类型,你可以随意修改其中的元素,添加或删除元素。函数内部对传递的 list 对象进行的修改同样也会影响到原始的 list 对象。

总结而言,set 和 list 在传参时都是通过引用传递,而不是通过值传递。这意味着对于可变的 set 和 list 对象,函数内部的修改都会反映到原始的对象上。需要注意的是,如果你想要在函数内部创建一个独立的 set 或 list 对象,可以使用 set() 或 list() 函数创建一个新的对象,并将原始对象的元素复制给这个新对象。

深拷贝和浅拷贝的区别?

poll和epoll的区别?

“poll” 和 “epoll” 是在 Linux 环境下用于实现事件驱动的 I/O 多路复用的机制,用于同时监听多个文件描述符的可读或可写状态。以下是它们之间的主要区别:

  1. 接口设计:

    • poll:poll 函数使用一个 pollfd 结构数组(包含文件描述符和待监听事件)来传递和存储参数,每次调用需要将所有待监听的文件描述符都传递给内核。
    • epoll:epoll 采用更加简洁的接口设计,通过调用 epoll_create 创建一个 epoll 对象,然后使用 epoll_ctl 函数向 epoll 对象中注册待监听的文件描述符和事件,通过 epoll_wait 获取已就绪的文件描述符。
  2. 数据结构效率:

    • poll:poll 函数需要遍历整个 pollfd 数组来查找已发生的事件,随着待监听的文件描述符数量增加,性能会线性下降。
    • epoll:epoll 使用红黑树和链表来存储待监听的文件描述符,因此在文件描述符数量较多时,性能较好,不会随着数量增加而降低。
  3. 触发模式支持:

    • poll:poll 只支持水平触发(Level Triggered,LT)模式,即当文件描述符就绪时,会一直触发可读或可写事件,直到处理完剩余数据。
    • epoll:epoll 支持水平触发模式(LT)和边缘触发模式(Edge Triggered,ET)。边缘触发模式只在文件描述符状态变化时通知一次,需要消耗更多的系统调用。
  4. 扩展性:

    • poll:poll 的可扩展性受制于每次调用时需要传递所有待监听的文件描述符,适用于文件描述符数量较少的场景。
    • epoll:epoll 可以使用边沿触发模式(ET)以及 epoll_wait 函数的 timeout 参数,保持较好的可扩展性和高性能,适用于大规模并发场景。

总体而言,epoll 在设计和性能上相对于 poll 有更多的优势,尤其是在大规模并发的 I/O 处理中。然而,具体选择使用 poll 还是 epoll 取决于具体的应用场景和需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/68425.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式】Head First 设计模式——抽象工厂模式 C++实现

设计模式最大的作用就是在变化和稳定中间寻找隔离点&#xff0c;然后分离它们&#xff0c;从而管理变化。将变化像小兔子一样关到笼子里&#xff0c;让它在笼子里随便跳&#xff0c;而不至于跳出来把你整个房间给污染掉。 设计思想 提供一个接口&#xff0c;让该接口负责创建一…

js获得相对路径文件,并上传到服务器

如何通过js获得相对路径文件 已知一个相对路径文件&#xff0c;如何使用js将该文件读取为File格式&#xff0c;最后上传到服务器中呢。 1.最简单的解决方案——fetch 代码 import ./index.scss// js通过相对路径获取文件 function FetchGetLocalFile() {const fetchLocalFile …

centos7升级openssh版本

linux升级openssh版本&#xff0c;升级到8.6p1 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.下载rpm包 2.编写一键安装脚本&#xff08;然后执行&#xff09; #把所有的rpm包&#xff0c;我都放到了/ydy目录&#xff0c;下面安装时&#xff0c;也指定了这个目录 #编…

mysql、MHA高可用配置即故障切换

MHA概述 一套优秀的MySQL高可用环境下故障切换和主从复制的软件 MHA的出现就是解决MySQL 单点的问题 MySQL故障过程中&#xff0c;MHA能做到0-30秒内自动完成故障切换 MHA能在故障切换的过程中最大程度上保证数据的一致性以达到真正意义上的高可用 MHA的组成&#xff08;核…

助力网络管理的利器:企业办公网络中的VLAN划分策略

企业办公网络的性能和安全性对员工的高效工作和信息安全具有重要意义。在实现这一目标时&#xff0c;VLAN&#xff08;Virtual Local Area Network&#xff09;划分在网络设计中发挥着至关重要的作用。通过将办公网络划分为多个虚拟局域网&#xff0c;VLAN划分可以实现网络资源…

uniapp - 倒计时组件-优化循环时间倒计时

使用定时器的规避方法 为了避免定时器误差导致倒计时计算错误&#xff0c;可以采用一些规避方法&#xff0c;比如将倒计时被中断时的剩余时间记录下来&#xff0c;重新开启定时器时再将这个剩余时间加到新的计算中。同时&#xff0c;为了避免定时器延迟&#xff0c;可以在每次执…

记一次Nginx代理Mysql服务的经历

背景&#xff1a; 根据组长背景描述&#xff0c;具备以下前提 1. Mysql服务器为 某A云厂商的RDS SAAS服务&#xff0c;但是不开通外网服务 2. EC2 服务器一台&#xff0c;某A云厂商LaaS服务&#xff0c;也不开通外网 3.阿里云服务器一台&#xff0c;这台服务器有服务需要连…

Web3面试最常见的10个问题

1、什么是web3&#xff1f;web2和web3的区别&#xff1f; web3是互联网的下一代形态,与当前主流的web2形态有着明显的区别: web2是中心化的,web3是去中心化的。 web2的平台由中心化机构控制,如Facebook、微信等。用户需要通过这些中心化平台才能进行互动。而web3基于区块链去…

5700A福禄克FLUKE 5700A多功能校准器

181/2461/8938Fluke 5700A/5720A 高精度多功能校准器 5700A: 世界级标准产品 通过不断的改进、提高&#xff0c;5700A已经演变为5700A系列II。这是福禄克公司生产的、经过大量测试证明、极为可靠的、高精度校准器。5700A已经在全世界的范围被看作是校准器的标准&#xff0c;具有…

直方图统计增强方法

直方图统计增强方法的原理&#xff1a;   直方图统计增强是一种基于像素值分布的图像增强技术&#xff0c;通过调整像素值的分布来增强图像的对比度和细节。其原理是根据图像的直方图信息&#xff0c;将原始像素值映射到一个新的像素值域&#xff0c;从而改变图像的亮度和对比…

用python开发一个炸金花小游戏

众所周知&#xfeff;扑克牌可谓是居家旅行、桌面交友的必备道具&#xff0c; 今天我们用 Python 来实现一个类似炸金花的扑克牌小游戏&#xff0c;先来看一下基本的游戏规则。 炸&#xff08;诈&#xff09;金花又叫三张牌&#xff0c;是在全国广泛流传的一种民间多人纸牌游戏…

【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;首先我们要知道后序遍历数组的最后一个元素必然是根节点&#xff0c;然后根据根节点在中序遍历数组中的…

postgres源码解析55 Brin Index--2(brinbuild流程)

上一篇讲解了brin index的基本概念以及页布局postgres源码解析54 Brin Index–1&#xff0c;后续会从源码角度对索引的构建、维护等方面进行深入讲解。 1 关键数据结构 2 brinbuild执行流程图 3 brinbuild 函数详解 1 首先调用brin_matepage_init初始化brin meta元数据页&…

【0904作业】QT 完成登陆界面跳转到聊天室+完成学生管理系统的查找和删除功能

一、完成登陆界面跳转到聊天室 1> 项目结构 2> 源码 ① .pro ②main #include "mywnd.h" #include"chatCli.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MyWnd w;w.show();Form f;QObject::co…

Lite transformer

图片以及思想来源请参考论文 Lite Transformer with Long-Short Range Attention 瓶颈结构&#xff08;bottleneck&#xff09;是否真的有效 注意力机制被广泛应用在诸多领域&#xff0c;包括自然语言处理&#xff0c;图像处理和视频处理。它通过计算所有输入元素的点积来建模…

低代码平台:IVX 重新定义编程

目录 &#x1f36c;一、写在前面 &#x1f36c;二、低代码平台是什么 &#x1f36c;三、为什么程序员和技术管理者不太可能接受“低代码”平台&#xff1f; &#x1f36d;1、不安全&#xff08;锁定特性&#xff09; &#x1f36d;2、不信任 &#x1f36c;四、IVX低代码平台 &a…

《阿里巴巴 Java 开发手册》(一)命名风格

《阿里巴巴 Java 开发手册》 一、编程规约(一)命名风格(二)常量定义(三)代码格式 一、编程规约 (一)命名风格 (二)常量定义 (三)代码格式

javaScript:DOM(父子/兄弟)常用属性

目录 前言 一.父子关系 父子关系的常用属性 childNodes 获取所有的子节点 children 获取所有的子元素&#xff08;dom元素&#xff09; firstChild 获取元素的第一个子节点&#xff0c;相当于 childNodes[0] firstElementChild 获取元素的第一个元素 相当于 children[0]…

Java是如何实现线程间通信的?

在Java中&#xff0c;线程间通信可以通过以下方式实现&#xff1a; 1.共享变量 线程可以通过共享的变量进行通信。多个线程可以读写同一个变量来交换信息。在这种情况下&#xff0c;需要确保线程对共享变量的访问是同步的&#xff0c;以避免数据竞争和不一致的结果。 以下是一…

spring service事务传播

spring定义的事务行为有以下几种&#xff1a; REQUIRED--支持当前事务&#xff0c;如果当前没有事务&#xff0c;就新建一个事务。这是最常见的选择。 SUPPORTS--支持当前事务&#xff0c;如果当前没有事务&#xff0c;就以非事务方式执行。 MANDATORY--支持当前事务&#xff…