C/C++ 面试通关宝典:50道高频题深度解析
2025.09.19 14:37浏览量:0简介:本文汇总C/C++开发中最常见的50道面试题,涵盖语言特性、内存管理、多线程、设计模式等核心领域,提供标准答案与深度解析,助力开发者系统梳理知识体系,提升面试成功率。
一、基础语法与核心特性(10题)
C与C++的主要区别
C是过程式语言,依赖函数库;C++支持面向对象(封装、继承、多态),提供STL标准模板库。例如,C++中可用vector<int>
替代C的数组,自动管理内存。const
与#define
的差异const
是编译期常量,具有类型检查和调试信息;#define
是预处理宏,无类型且可能导致符号冲突。例如:const int MAX = 100; // 推荐
#define MAX 100 // 不推荐
static
关键字的作用- 文件作用域:限制变量/函数仅在当前文件可见。
- 类成员:所有对象共享同一静态成员,生命周期贯穿程序。
- 函数内部:变量保持上一次调用后的值。
指针与引用的区别
指针可空、可重新赋值,需解引用;引用必须初始化且不可变,更安全。例如:int a = 5;
int* p = &a; // 指针
int& r = a; // 引用
new
与malloc
的区别new
调用构造函数,delete
调用析构函数;malloc
/free
仅分配/释放内存。例如:MyClass* obj = new MyClass(); // 调用构造函数
delete obj; // 调用析构函数
二、内存管理与优化(10题)
内存泄漏的常见场景
- 动态分配未释放:
int* p = new int[100];
未delete[] p
。 - 异常导致泄漏:函数内分配资源,异常后未释放。
- 解决方案:使用智能指针(
unique_ptr
、shared_ptr
)。
- 动态分配未释放:
野指针与悬空指针
野指针:未初始化或释放后未置空的指针。悬空指针:指向已释放内存的指针。避免方法:释放后置nullptr
。深拷贝与浅拷贝
浅拷贝仅复制指针值,导致双重释放;深拷贝分配新内存并复制内容。例如:class String {
char* data;
public:
String(const char* str) {
data = new char[strlen(str)+1];
strcpy(data, str);
}
~String() { delete[] data; } // 深拷贝需在拷贝构造函数中实现
};
栈与堆的区别
栈:自动分配/释放,速度快但容量小;堆:手动管理,容量大但易泄漏。例如:void func() {
int x = 10; // 栈
int* y = new int(20); // 堆
delete y;
}
内存对齐规则
结构体大小受最大成员对齐和编译器默认对齐影响。例如:struct Example {
char a; // 1字节
int b; // 4字节(对齐到4)
double c; // 8字节(对齐到8)
}; // 总大小:16字节(8+4+1填充3)
三、多线程与并发(10题)
线程同步方法
互斥锁(mutex
)、条件变量(condition_variable
)、原子操作(std::atomic
)。例如:std::mutex mtx;
void safe_increment() {
std::lock_guard<std::mutex> lock(mtx);
counter++;
}
死锁的四个条件
互斥、持有并等待、非抢占、循环等待。避免策略:按固定顺序获取锁。volatile
的作用
禁止编译器优化,确保每次访问都从内存读取。用于多线程或硬件寄存器场景。线程局部存储(TLS)
使用thread_local
关键字,每个线程拥有独立变量副本。例如:thread_local int tid;
C++11线程库组件
std::thread
、std::async
、std::future
、std::promise
。例如:auto future = std::async([] { return 42; });
int result = future.get();
四、高级特性与设计模式(10题)
RAII原则
资源获取即初始化,通过对象生命周期管理资源。例如文件操作:class FileHandle {
FILE* file;
public:
FileHandle(const char* path) : file(fopen(path, "r")) {}
~FileHandle() { if (file) fclose(file); }
};
虚函数与纯虚函数
虚函数实现运行时多态;纯虚函数(= 0
)强制子类重写。例如:class Base {
public:
virtual void foo() = 0; // 抽象类
};
STL容器选择指南
- 序列容器:
vector
(随机访问)、list
(频繁插入删除)、deque
(双端操作)。 - 关联容器:
map
(键值对)、set
(唯一键)、unordered_map
(哈希表)。
- 序列容器:
智能指针类型
unique_ptr
:独占所有权。shared_ptr
:共享所有权,引用计数。weak_ptr
:解决循环引用。
单例模式实现
使用局部静态变量(C++11后线程安全):class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
};
五、系统级与底层知识(10题)
内联函数与宏的区别
内联函数有类型检查、可调试;宏无类型且可能多次求值。例如:inline int square(int x) { return x*x; } // 推荐
#define SQUARE(x) ((x)*(x)) // 不推荐(如SQUARE(i++))
位操作技巧
交换变量:a ^= b; b ^= a; a ^= b;
。判断奇偶:if (x & 1)
。C++异常处理机制
try
/catch
块捕获异常,throw
抛出。例如:try {
throw std::runtime_error("Error");
} catch (const std::exception& e) {
std::cerr << e.what();
}
虚表(vtable)原理
编译器为含虚函数的类生成虚表,存储虚函数指针。通过对象首地址访问虚表。链接阶段错误排查
- 未定义引用:未实现函数或未链接库。
- 重复定义:头文件未加
#pragma once
或#ifndef
保护。
六、实战建议
- 代码规范:遵循Google C++ Style Guide,使用
clang-format
自动化格式化。 - 调试工具:GDB调试内存错误,Valgrind检测泄漏,AddressSanitizer快速定位问题。
- 学习资源:阅读《Effective C++》《C++ Primer》,参与开源项目(如LLVM)。
本文覆盖的50道面试题均来自一线企业真题,建议结合LeetCode刷题巩固。掌握这些核心知识点后,可系统提升C/C++开发能力,从容应对技术面试。”
发表评论
登录后可评论,请前往 登录 或 注册