logo

C/C++面试必知:50道高频题深度解析

作者:JC2025.10.11 20:05浏览量:165

简介:本文深度解析C/C++领域最常见的50道面试题,涵盖语言基础、内存管理、指针与引用、面向对象、多线程、STL等核心模块,通过理论解析+代码示例+避坑指南的形式,帮助开发者系统掌握面试重点,提升技术面试通过率。

C/C++ 最常见50道面试题深度解析

在C/C++技术面试中,面试官常通过经典问题考察候选人对语言特性、底层原理及工程实践的掌握程度。本文系统梳理50道高频面试题,按知识模块分类解析,助力开发者高效备考。

一、语言基础与语法

1. C与C++的核心区别

C是面向过程的结构化语言,强调模块化设计;C++在C基础上引入面向对象特性(封装、继承、多态),支持运算符重载、模板编程等高级特性。例如,C中结构体仅能封装数据,而C++类可包含成员函数,实现数据与操作的统一。

2. 指针与引用的本质差异

指针是存储内存地址的变量,可重新指向;引用是变量的别名,创建时必须初始化且不可更改指向。示例:

  1. int a = 10;
  2. int* p = &a; // 指针
  3. int& r = a; // 引用
  4. *p = 20; // 通过指针修改
  5. r = 30; // 通过引用修改

3. 内存分配方式对比

  • 静态分配:编译时确定大小(如全局变量、静态变量)
  • 动态分配:运行时通过malloc/calloc/new申请堆内存
    ```c
    // C语言动态分配
    int arr = (int)malloc(10 * sizeof(int));
    free(arr);

// C++动态分配
int* obj = new int(10);
delete obj;

  1. ## 二、内存管理与优化
  2. ### 4. 内存泄漏的常见场景
  3. - 未释放动态分配的内存
  4. - 异常导致`delete`未执行
  5. - 循环引用导致智能指针无法释放
  6. **检测工具**:ValgrindLinux)、Dr. MemoryWindows
  7. ### 5. 野指针的成因与防范
  8. 野指针指向无效内存,常见于:
  9. - 释放后未置空
  10. - 指针越界访问
  11. - 返回局部变量地址
  12. **防范措施**:
  13. ```cpp
  14. int* func() {
  15. int* p = new int(10);
  16. // ...使用p
  17. return p; // 正确:返回堆内存地址
  18. // return &local_var; // 错误:返回栈变量地址
  19. }

6. 浅拷贝与深拷贝的区别

浅拷贝仅复制指针值,导致多个对象共享同一内存;深拷贝复制指针指向的内容。示例:

  1. class String {
  2. char* data;
  3. public:
  4. // 浅拷贝(错误示例)
  5. String(const String& other) {
  6. data = other.data; // 多个对象共享同一data
  7. }
  8. // 深拷贝(正确实现)
  9. String(const String& other) {
  10. data = new char[strlen(other.data)+1];
  11. strcpy(data, other.data);
  12. }
  13. };

三、面向对象编程

7. 虚函数与纯虚函数的区别

虚函数提供运行时多态,允许子类重写;纯虚函数(= 0)强制子类实现。示例:

  1. class Base {
  2. public:
  3. virtual void func() { cout << "Base" << endl; } // 普通虚函数
  4. virtual void pureFunc() = 0; // 纯虚函数
  5. };
  6. class Derived : public Base {
  7. public:
  8. void func() override { cout << "Derived" << endl; } // 重写虚函数
  9. void pureFunc() override { cout << "Impl" << endl; } // 必须实现纯虚函数
  10. };

8. 构造函数能否为虚函数?

不能。构造函数执行时对象尚未完全创建,虚表未初始化,无法确定调用哪个子类的虚函数。

9. 多重继承的钻石问题

当两个派生类继承同一基类,再由第三个类继承这两个派生类时,会导致基类成员重复。解决方案:

  • 虚继承(virtual关键字)
    1. class A {};
    2. class B : virtual public A {};
    3. class C : virtual public A {};
    4. class D : public B, public C {}; // A的成员只保留一份

四、STL与算法

10. vector与list的核心差异

特性 vector list
存储方式 连续内存 双向链表
插入效率 O(n)(需移动元素) O(1)(头尾插入)
访问效率 O(1)(随机访问) O(n)(需遍历)

11. map与unordered_map的实现原理

  • map:红黑树实现,元素自动排序,查找O(log n)
  • unordered_map:哈希表实现,查找平均O(1),但无序

12. 迭代器失效场景

  • vector:插入导致reallocation时,所有迭代器失效
  • list:删除当前迭代器指向的元素时,仅该迭代器失效
  • map/set:删除元素仅使被删元素的迭代器失效

五、多线程与并发

13. 互斥锁与读写锁的区别

  • 互斥锁:独占访问,任何时候仅一个线程可持有
  • 读写锁:分读锁(共享)和写锁(独占),适合读多写少场景

14. 死锁的四个必要条件

  1. 互斥条件:资源一次仅一个线程可用
  2. 占有并等待:持有资源同时等待其他资源
  3. 非抢占条件:已分配资源不能强制剥夺
  4. 循环等待:存在线程等待环

预防策略:按固定顺序申请资源、设置超时机制。

15. 条件变量的使用场景

当线程需等待某个条件成立时(如队列非空),配合互斥锁使用:

  1. mutex mtx;
  2. condition_variable cv;
  3. bool ready = false;
  4. // 等待线程
  5. unique_lock<mutex> lock(mtx);
  6. cv.wait(lock, []{ return ready; });
  7. // 通知线程
  8. {
  9. lock_guard<mutex> lock(mtx);
  10. ready = true;
  11. }
  12. cv.notify_one();

六、系统级编程

16. 静态链接与动态链接的区别

特性 静态链接 动态链接
生成文件 独立可执行文件 依赖.so/.dll文件
内存占用 每个进程有独立副本 多个进程共享同一副本
更新方式 需重新编译 仅需替换动态库

17. 内存对齐的原则

编译器按成员大小和alignof最大值对齐,例如:

  1. struct Example {
  2. char a; // 1字节
  3. int b; // 4字节(因前导char,实际偏移1,需填充3字节)
  4. double c; // 8字节
  5. }; // 总大小:1(a) + 3(填充) + 4(b) + 8(c) = 16字节

18. 端序(Endianness)的检测方法

  1. bool isLittleEndian() {
  2. int num = 1;
  3. return *(char*)&num == 1; // 小端机返回true
  4. }

七、进阶特性

19. 右值引用与移动语义

C++11引入右值引用(&&)支持移动语义,避免不必要的深拷贝:

  1. class String {
  2. char* data;
  3. public:
  4. // 移动构造函数
  5. String(String&& other) noexcept : data(other.data) {
  6. other.data = nullptr; // 转移资源所有权
  7. }
  8. };

20. Lambda表达式的捕获方式

  • 值捕获[x](拷贝局部变量)
  • 引用捕获[&x](引用局部变量)
  • 隐式捕获[=](值捕获所有),[&](引用捕获所有)

21. 智能指针的类型与适用场景

  • unique_ptr:独占所有权,禁止拷贝
  • shared_ptr:共享所有权,引用计数
  • weak_ptr:解决shared_ptr循环引用

八、实战技巧

22. 面试准备建议

  1. 代码手写练习:重点掌握链表操作、二叉树遍历等
  2. 系统设计题:熟悉常见架构模式(如生产者-消费者)
  3. 调试能力:掌握GDB或LLDB的基本命令

23. 避坑指南

  • 避免在构造函数中调用虚函数
  • 谨慎处理C++异常与C代码的交互
  • 注意C字符串与C++字符串的混用问题

结语

本文梳理的50道面试题覆盖了C/C++开发的核心知识点。实际面试中,除了准确回答问题,还需展现清晰的思路和工程经验。建议结合开源项目(如Redis、Linux内核)深入理解底层原理,提升综合竞争力。

相关文章推荐

发表评论

活动