C/C++面试必知:50道高频题深度解析
2025.09.19 14:37浏览量:6简介:本文汇总C/C++领域最常见的50道面试题,涵盖语言基础、内存管理、指针与引用、多线程等核心知识点,为开发者提供系统性复习框架与解题思路。
C/C++ 最常见50道面试题深度解析
一、语言基础与语法(10题)
C与C++的核心区别
C是过程式语言,依赖函数和结构体;C++是面向对象语言,支持类、继承、多态。C++在C基础上增加了模板、异常处理、STL等特性。例如,C中用malloc/free管理内存,C++则推荐new/delete或智能指针。static关键字的作用- 局部变量:延长生命周期至程序结束,仅初始化一次。
- 全局变量:限制作用域为当前文件(内部链接)。
- 成员变量:所有对象共享同一副本。
- 成员函数:只能访问静态成员,无
this指针。
const与define的区别const是编译期常量,有类型检查和作用域;#define是预处理宏,直接文本替换,可能导致边界问题(如#define MAX 100在调试时无法查看值)。指针与引用的区别
指针可重新赋值,可为NULL;引用是别名,必须初始化且不可更改绑定。例如:int a = 10;int* p = &a; // 指针int& r = a; // 引用p = nullptr; // 合法// r = nullptr; // 编译错误
sizeof与strlen的区别sizeof是运算符,返回对象或类型的字节大小(如char arr[10]; sizeof(arr) = 10);strlen是函数,返回字符串长度(不包括\0)。
二、内存管理与动态分配(8题)
内存泄漏的常见场景
- 忘记
delete动态分配的对象。 - 异常导致
delete未执行。 - 循环引用(智能指针需用
weak_ptr解决)。
示例:void leak() {int* p = new int[100];throw std::runtime_error("error"); // 泄漏发生delete[] p;}
- 忘记
new与malloc的区别new调用构造函数,delete调用析构函数;malloc/free仅分配/释放内存。new失败时抛出std::bad_alloc,malloc返回NULL。智能指针的类型与适用场景
unique_ptr:独占所有权,不可复制。shared_ptr:共享所有权,引用计数。weak_ptr:解决循环引用,不增加计数。
示例:std::unique_ptr<int> up(new int(10));std::shared_ptr<int> sp1(new int(20));std::shared_ptr<int> sp2 = sp1; // 计数+1
浅拷贝与深拷贝的区别
浅拷贝仅复制指针值,导致多个对象共享同一内存;深拷贝分配新内存并复制内容。需自定义拷贝构造函数时(如含指针的类),必须实现深拷贝。placement new的用途
在已分配的内存上构造对象,常用于内存池或嵌入式系统。示例:char buffer[sizeof(MyClass)];MyClass* obj = new (buffer) MyClass(); // 在buffer上构造
三、面向对象与多态(12题)
虚函数与纯虚函数的区别
虚函数提供默认实现,子类可重写;纯虚函数(= 0)无实现,强制子类重写。含纯虚函数的类为抽象类,不能实例化。构造函数能否为虚函数?
不能。构造函数执行时对象未完全构造,vptr未初始化,无法确定虚函数表。多重继承的钻石问题与虚继承
多重继承可能导致基类子对象重复(如class D : public B1, public B2,若B1和B2均继承A)。虚继承(virtual)可解决:class A {};class B1 : virtual public A {};class B2 : virtual public A {};class D : public B1, public B2 {}; // 仅一个A子对象
override与final关键字的作用override显式标记重写虚函数,编译期检查是否匹配基类声明;final禁止子类进一步重写或继承。RTTI(运行时类型识别)的机制
通过dynamic_cast和typeid实现。dynamic_cast用于安全向下转型,typeid返回对象的类型信息(需包含<typeinfo>)。
四、模板与泛型编程(8题)
函数模板与类模板的区别
函数模板实例化时推导类型参数;类模板需显式指定类型。示例:template <typename T>T max(T a, T b) { return a > b ? a : b; } // 函数模板template <typename T>class Stack { /*...*/ }; // 类模板
模板特化与偏特化
全特化:为所有模板参数指定具体类型。偏特化:部分参数特化。示例:template <typename T>class A {}; // 原模板template <>class A<int> {}; // 全特化template <typename T>class A<T*> {}; // 偏特化(指针类型)
可变参数模板的应用
用于实现泛型打印函数:void print() {}template <typename T, typename... Args>void print(T first, Args... args) {std::cout << first << std::endl;print(args...);}
五、多线程与并发(6题)
std::mutex与std::lock_guard的配合lock_guard在构造时加锁,析构时自动释放,避免忘记解锁。示例:std::mutex mtx;{std::lock_guard<std::mutex> lock(mtx);// 临界区} // 自动解锁
条件变量
std::condition_variable的使用
需配合std::unique_lock和谓词防止虚假唤醒:std::mutex mtx;std::condition_variable cv;bool ready = false;// 等待线程std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return ready; });// 通知线程{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one();
六、STL与算法(6题)
vector与list的适用场景vector随机访问快(O(1)),插入/删除尾部快(O(1)),中间插入慢(O(n));list双向链表,插入/删除快(O(1)),随机访问慢(O(n))。std::sort与std::stable_sort的区别std::sort通常用快速排序或内省排序,不稳定;stable_sort保证相等元素顺序,通常用归并排序。
七、高级特性(10题)
Lambda表达式的捕获方式
- 值捕获:
[x](副本)。 - 引用捕获:
[&x](可能悬空)。 - 隐式捕获:
[=](值)、[&](引用)。
示例:int x = 10;auto f = [=]() { return x + 1; }; // 值捕获
- 值捕获:
noexcept关键字的作用
标记函数是否可能抛出异常,影响移动语义和std::vector的重新分配行为。constexpr与编译期计算constexpr函数在编译期求值,需满足简单条件(如无循环或递归)。示例:constexpr int factorial(int n) {return n <= 1 ? 1 : n * factorial(n - 1);}
八、系统级与底层知识(6题)
内存对齐的规则
结构体成员按最大对齐数排列,总大小为对齐数的整数倍。示例:struct A {char c; // 1字节int i; // 4字节(对齐到4)double d; // 8字节(对齐到8)}; // sizeof(A) = 16(1 + 3填充 + 4 + 8)
volatile关键字的用途
禁止编译器优化,确保每次访问都从内存读取(常用于硬件寄存器或多线程共享变量)。
九、综合应用题(4题)
实现一个线程安全的单例模式
使用局部静态变量(C++11后线程安全)或双重检查锁定:class Singleton {public:static Singleton& getInstance() {static Singleton instance;return instance;}Singleton(const Singleton&) = delete;private:Singleton() {}};
设计一个内存池
关键点:预分配大块内存,分割为固定大小块,用链表管理空闲块。需处理对齐和碎片问题。解析字符串中的整数(如
"123"→123)
需处理符号、溢出和非法字符:int parseInt(const char* str) {int sign = 1, result = 0;if (*str == '-') { sign = -1; str++; }while (*str >= '0' && *str <= '9') {int digit = *str - '0';if (result > (INT_MAX - digit) / 10) throw std::overflow_error("overflow");result = result * 10 + digit;str++;}return sign * result;}
备考建议
- 分模块复习:按语言基础、内存管理、面向对象等分类,每日攻克1-2个模块。
- 动手实践:对每个知识点编写代码验证,如实现智能指针或线程池。
- 模拟面试:与同伴互相提问,记录回答时间并优化表达。
- 查阅文档:熟悉
cppreference.com等权威资料,避免依赖非标准实现。
通过系统性复习这50道高频题,开发者可全面掌握C/C++的核心知识点,在面试中展现扎实的技术功底。

发表评论
登录后可评论,请前往 登录 或 注册