C++部分

  1. 野指针

    1. 没有初始化的指针为野指针,导致使用时崩溃
    2. 扩展:悬垂指针,通过delete回收资源后,没有赋值为空,再次使用,由于指向的内存被回收了,导致崩溃
      扩充
    • 解决方法
      • 在指针被delete后,将指针赋值为nullptr,防止悬垂指针。
      • 使用智能指针(std::unique_ptrstd::shared_ptr),自动管理内存,减少手动错误。
  2. 析构函数

    1. C++ 析构函数主要是为了在对象被销毁时回收构造时申请的资源
    2. 扩展:可以基于RAII思想,管理对象资源的生命周期
      扩充
    • 析构函数的特性
      • 如果类中包含指针成员,析构函数必须显式释放内存,否则会导致内存泄漏。
      • 基类的析构函数应声明为virtual,确保派生类析构时正确调用基类析构函数。
  3. 内存布局

    1. .data: 初始化的全局变量
    2. .rodata: 存储常量
    3. .bss: 未初始化的全局变量,默认初始化为0
    4. .text: 存储函数
      扩充
    • 堆与栈
      • :用于函数调用、局部变量存储,自动分配和释放,快速且安全。
      • :动态内存分配,生命周期由程序员控制,容易产生内存泄漏。
  4. 内存分配

    1. malloc, new 在堆上申请空间
      扩充
    • 区别
      • malloc返回void*,不调用构造函数,使用时需要显式类型转换。
      • new返回对象类型指针,自动调用构造函数并初始化内存。
    • 释放内存
      • malloc配合freenew配合delete,不能混用,否则会引发未定义行为。
  5. 多线程要注意什么

    1. 数据竞争
    2. 锁的使用
      扩充
    • 常见问题
      • 死锁:多个线程循环等待资源,导致无法继续执行。
      • 线程安全:使用互斥锁(std::mutex)、条件变量等同步机制防止资源争用。
    • 优化
      • 使用std::lock_guardstd::unique_lock管理锁,防止忘记释放锁。
  6. 单例模式

    1. 为什么使用单例
      扩充
    • 单例的作用
      • 确保类只有一个实例,且提供全局访问点。
      • 常用于日志、配置管理、数据库连接等场景。
    • 实现方式
      • 懒汉模式(延迟初始化)
      • 饿汉模式(程序启动时初始化)
      • 使用std::call_oncestd::mutex保证线程安全。

项目部分

  1. 即时通讯软件,1对1聊天的聊天记录如何保存,群组的呢
    回答

    • 1对1聊天记录:可以保存到本地数据库(如SQLite)或者云端服务器,按用户ID建立索引以便快速查询。
    • 群组聊天记录:可以使用分布式数据库,按群ID和消息时间戳存储,便于同步和检索。
  2. 登录应该保存用户的哪些信息
    回答

    • 用户ID、用户名
    • 用户凭据(如Token、加密后的密码)
    • 登录状态和过期时间
    • 设备信息(如设备ID)
  3. 聊天界面有多种气泡,如文本,语音,图片。在接收到消息时,本地客户端如何判断是哪种类型的气泡
    回答

    • 消息格式应采用统一的消息协议,包含消息类型字段(如文本、语音、图片)。
    • 通过协议解析消息,判断消息类型,并调用对应的UI组件进行渲染。
  4. 如何实现消息的撤回
    回答

    • 在服务端和客户端记录消息的唯一ID。
    • 用户发起撤回请求,服务端验证权限后标记该消息为“撤回状态”。
    • 客户端接收到撤回指令后更新消息显示状态,如提示“消息已撤回”。
  5. 离线消息如何持久化
    回答

    • 服务端将离线消息存储到数据库或缓存中,按用户ID进行索引。
    • 当用户上线时,查询对应的离线消息并推送到客户端。
    • 客户端收到离线消息后,存储到本地持久化数据库(如SQLite)。