简介:本文汇总了C/C++开发领域最常见的50道面试题,涵盖语言特性、内存管理、指针与引用、多线程、设计模式等核心知识点,提供详细解答与代码示例,帮助开发者系统梳理知识体系,提升面试成功率。
在C/C++开发岗位的面试中,技术问题往往围绕语言核心特性、内存管理、并发编程、系统设计等维度展开。本文精选50道高频面试题,从基础到进阶,结合代码示例与理论分析,帮助开发者高效备考。
static关键字的作用static在C/C++中有三种核心用法:
void counter() {static int count = 0; // 只初始化一次count++;printf("%d\n", count);}
const与#define的区别#define是预处理指令,直接文本替换;const是类型安全的常量const变量可能分配存储空间,#define不占内存const变量可在调试器中查看,宏无法直接调试| 特性 | 指针 | 引用 |
|---|---|---|
| 初始化 | 可不初始化 | 必须初始化 |
| 可空性 | 可为NULL | 不可为空 |
| 重新绑定 | 可指向其他对象 | 绑定后不可更改 |
| 内存占用 | 占用存储空间 | 不占用额外空间 |
结构体内存对齐遵循:
struct Example {char a; // 1字节int b; // 4字节(对齐到4)double c; // 8字节(对齐到8)}; // 总大小:1(padding3) + 4 + 8 = 16字节
volatile的作用强制编译器不优化对变量的访问,常用于:
malloc与new的区别| 特性 | malloc |
new |
|---|---|---|
| 调用方式 | 函数 | 运算符 |
| 初始化 | 不初始化内存 | 可调用构造函数 |
| 失败处理 | 返回NULL | 抛出std::bad_alloc |
| 大小计算 | 需显式指定字节数 | 自动计算对象大小 |
new/malloc是否有对应delete/freestd::unique_ptr/std::shared_ptr产生原因:
避免方法:
nullptr
// 浅拷贝示例(错误)typedef struct {char* data;} String;String shallow_copy(String src) {String dest;dest.data = src.data; // 危险!共享同一内存return dest;}
| 特性 | 互斥锁 | 读写锁 |
|---|---|---|
| 读写权限 | 独占访问 | 读共享,写独占 |
| 适用场景 | 高竞争写操作 | 读多写少场景 |
| 性能 | 高竞争时性能下降 | 读操作并发提升性能 |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;bool ready = false;// 等待线程pthread_mutex_lock(&mutex);while (!ready) {pthread_cond_wait(&cond, &mutex);}// 临界区操作pthread_mutex_unlock(&mutex);// 通知线程pthread_mutex_lock(&mutex);ready = true;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);
std::atomic
bool compare_and_swap(int* ptr, int oldval, int newval) {if (*ptr == oldval) {*ptr = newval;return true;}return false;}
使用__thread(GCC)或thread_local(C++11)定义线程私有变量:
__thread int thread_local_var = 0;void* thread_func(void* arg) {thread_local_var = 42; // 每个线程独立副本return NULL;}
通过对象生命周期管理资源,典型应用:
class FileHandler {FILE* fp;public:FileHandler(const char* filename) : fp(fopen(filename, "r")) {if (!fp) throw std::runtime_error("Open failed");}~FileHandler() {if (fp) fclose(fp);}// 禁用拷贝FileHandler(const FileHandler&) = delete;FileHandler& operator=(const FileHandler&) = delete;};
class Base {public:virtual void foo() { printf("Base\n"); }};class Derived : public Base {public:void foo() override { printf("Derived\n"); }};Base* obj = new Derived();obj->foo(); // 输出"Derived"
| 类型 | 所有权语义 | 适用场景 |
|---|---|---|
unique_ptr |
独占所有权 | 明确单一所有者 |
shared_ptr |
共享所有权 | 多个所有者需要共存 |
weak_ptr |
非拥有观察者 | 打破循环引用 |
编译时计算斐波那契数列:
template<int N>struct Fibonacci {static const int value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;};template<>struct Fibonacci<0> { static const int value = 0; };template<>struct Fibonacci<1> { static const int value = 1; };int main() {std::cout << Fibonacci<10>::value; // 输出55}
std::move
bool is_little_endian() {int num = 1;return *(char*)&num == 1;}
| 约定 | 参数传递 | 栈清理 | 命名修饰 |
|---|---|---|---|
__cdecl |
右到左 | 调用方 | _func |
__stdcall |
右到左 | 被调方 | _func@n |
__fastcall |
寄存器+栈 | 被调方 | @func@n |
#include <sys/mman.h>int fd = open("file.bin", O_RDWR);void* addr = mmap(NULL, file_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);// 使用addr访问文件内容munmap(addr, file_size);close(fd);
#include <signal.h>void handler(int sig) {write(STDOUT_FILENO, "Signal caught\n", 15);}int main() {signal(SIGINT, handler);while (1) pause();}
| 方式 | 特点 | 典型应用 |
|---|---|---|
| 管道 | 单向字节流 | 命令行管道 |
| 共享内存 | 最高效 | 大型数据交换 |
| 消息队列 | 结构化数据 | 进程间消息传递 |
| 套接字 | 网络支持 | 分布式系统 |
掌握这50道面试题不仅能帮助通过技术面试,更能深化对C/C++语言本质的理解。建议结合《Effective C++》、《C++ Primer》等经典书籍系统学习,同时通过LeetCode等平台练习算法题,全面提升编程能力。