拼多多面试题记录

发布于:2025-02-21 ⋅ 阅读:(33) ⋅ 点赞:(0)

0 问题汇总

在这里插入图片描述
以下内容为经过豆包的回答,不一定对,只为自己学习使用

1 C++11有哪些新特性?

  1. 语言易用性增强
    统一的初始化语法
    C++11 引入了花括号初始化器(列表初始化),可以用于各种类型的初始化,包括基本类型、数组、容器等,并且可以防止窄化转换。
    自动类型推导
    auto 关键字:编译器可以根据初始化表达式自动推导变量的类型,减少代码的冗余。
    decltype 关键字:用于在编译时推导表达式的类型,常用于模板编程。
    范围 for 循环
    可以更方便地遍历容器和数组,无需手动管理迭代器或索引。
  2. 智能指针
    C++11 引入了三种智能指针,用于自动管理动态分配的内存,避免内存泄漏。
    std::unique_ptr:独占式智能指针,同一时间只能有一个 unique_ptr 指向某个对象。
    std::shared_ptr:共享式智能指针,多个 shared_ptr 可以指向同一个对象,通过引用计数来管理对象的生命周期。
    std::weak_ptr:弱引用智能指针,用于解决 std::shared_ptr 的循环引用问题。
  3. 多线程支持
    C++11 标准库提供了对多线程编程的原生支持。
    std::thread:用于创建和管理线程。
    std::mutex 和 std::lock_guard:用于线程同步,std::mutex 是互斥锁,std::lock_guard 是 RAII 风格的锁管理类。
  4. Lambda 表达式
    Lambda 表达式是一种匿名函数,可用于创建临时的、一次性使用的函数对象,常用于函数式编程和作为回调函数。
  5. 右值引用和移动语义
    右值引用:使用 && 表示,用于区分左值和右值,主要用于实现移动语义。
    移动语义:通过移动构造函数和移动赋值运算符,避免不必要的对象复制,提高性能。
  6. 其他特性
    std::tuple:用于创建和操作多个不同类型的值的元组。
    std::array:是一个固定大小的数组容器,比原生数组更安全和方便。
    std::unordered_map 和 std::unordered_set:基于哈希表实现的关联容器,提供了快速的查找和插入操作。

2 一个C++源文件从文本到可执行文件经历的过程

一个 C++ 源文件从文本形式转变为可执行文件,通常要经过预处理、编译、汇编和链接这四个主要阶段,下面为你详细介绍每个阶段的具体内容和作用。

  1. 预处理阶段
    主要任务:预处理器根据源文件里的预处理指令对源文件开展文本替换与处理,最终生成一个经过预处理的中间文件。
    常见预处理指令及处理方式
    #include:把指定的头文件内容插入到当前源文件里。例如,#include 会将标准输入输出库的头文件内容插入到代码中。
    #define:进行宏定义,把代码中出现的宏替换成定义的值。比如 #define PI 3.14159,之后代码里的 PI 都会被替换成 3.14159。
    #ifdef、#ifndef、#endif 等:用于条件编译,依据条件决定是否编译某段代码。
  2. 编译阶段
    主要任务:编译器将经过预处理的源文件翻译成汇编代码。在此阶段,编译器会进行语法分析、语义分析、代码优化等操作,同时检查代码中的语法错误和逻辑错误。
    工作流程
    词法分析:把源代码分解成一个个的词法单元(像关键字、标识符、运算符等)。
    语法分析:根据词法单元构建语法树,检查代码是否符合 C++ 语法规则。
    语义分析:对语法树进行语义检查,例如类型检查、作用域检查等。
    代码优化:对代码进行优化,提升程序的执行效率,例如常量折叠、循环展开等。
    生成汇编代码:把优化后的代码转换为汇编语言代码。
  3. 汇编阶段
    主要任务:汇编器将汇编代码转换为机器语言代码,生成目标文件。目标文件是二进制文件,包含了机器指令和数据,但还不能直接运行。
    工作方式:汇编器会把汇编指令逐行翻译成对应的机器指令,同时处理符号表和重定位信息。
  4. 链接阶段
    主要任务:链接器将多个目标文件和所需的库文件链接在一起,生成可执行文件。在程序开发中,一个项目通常会包含多个源文件,每个源文件会生成对应的目标文件,同时还可能会使用到系统库或第三方库。链接器的作用就是将这些文件组合成一个完整的可执行程序。
    链接类型
    静态链接:把库文件的代码直接复制到可执行文件中,这样可执行文件在运行时不需要依赖外部的库文件,但会使可执行文件的体积变大。
    动态链接:可执行文件在运行时才会加载所需的库文件,多个程序可以共享同一个库文件,减少了磁盘空间的占用。
    综上所述,一个 C++ 源文件从文本到可执行文件需要依次经过预处理、编译、汇编和链接四个阶段,每个阶段都有其特定的任务和作用,最终生成可以在操作系统上运行的可执行程序。

3malloc的原理

malloc 是 C 语言标准库中用于动态内存分配的函数,其原型为 void *malloc(size_t size),作用是在堆内存中分配指定大小(size 字节)的连续空间,并返回一个指向该内存块起始地址的指针。若分配失败,则返回 NULL。下面详细介绍其原理:
堆内存管理基础
在操作系统里,每个进程都有独立的虚拟地址空间,堆是其中用于动态内存分配的区域,它从低地址向高地址增长。操作系统借助特定的数据结构来管理堆内存,记录空闲内存块和已分配内存块的相关信息。
malloc 实现的关键要素
malloc 实现的关键要素

  1. 空闲内存块管理
    空闲链表(Free List):多数 malloc 实现会维护一个空闲链表,用于记录堆中可用的空闲内存块。每个空闲内存块一般包含一个头部信息,其中记录了该内存块的大小以及指向下一个空闲内存块的指针。通过这种链表结构,malloc 可以快速查找和管理空闲内存。
    内存池(Memory Pool):为提升内存分配效率,malloc 通常会预先从操作系统申请一大块内存作为内存池。后续的分配和回收操作就在这个内存池中进行,减少了与操作系统的频繁交互。
  2. 分配算法
    首次适配算法(First - Fit):当调用 malloc 时,它会遍历空闲链表,找到第一个大小足够的空闲内存块。若找到合适的内存块,会将其从空闲链表中移除。若该内存块比所需大小大,会将多余部分拆分成一个新的空闲内存块,并重新插入到空闲链表中。
    最佳适配算法(Best - Fit):除了首次适配算法,有些实现采用最佳适配算法。此算法会遍历空闲链表,