以下是整合后的约 120 道 C++ 基础校招面试题单,部分难度较高的题目标注为附加题:
一、基础语法与变量类型(16 题)
- C++ 中有哪些基本数据类型?它们的大小和取值范围是怎样的?
- 解释常量和常量表达式的区别,以及
const
和constexpr
的使用场景。 - 引用和指针有什么区别?在什么情况下应该使用引用而不是指针?
- 如何定义和初始化一个二维数组?数组名和指针有什么联系和区别?
- 枚举类型在 C++ 中有什么作用?如何定义和使用枚举类型?
- 类型转换有哪几种?分别在什么场景下使用?
- 解释
auto
和decltype
关键字的作用,以及它们在 C++ 中的使用场景。 void*
指针有什么特点和用途?使用时需要注意什么?- 位运算有哪些?在实际开发中有哪些应用场景?
- 字符数组和字符串对象(如
std::string
)有什么区别?如何进行相互转换? - 宽字符类型(如
wchar_t
)和普通字符类型有什么不同?在什么场景下会用到宽字符? - 如何定义和使用联合体(
union
)?联合体有什么特点和限制? - 静态常量成员变量和普通常量成员变量有什么区别?如何初始化静态常量成员变量?
- 如何使用
typedef
和using
来定义类型别名?它们之间有什么区别? - 解释
register
关键字的作用,在现代编译器中它还有实际意义吗? - C++ 中
struct
和class
的区别是什么?为什么游戏引擎常用 POD 类型?
二、函数与作用域(12 题)
- 函数重载的规则是什么?编译器如何区分重载的函数?
- 什么是函数模板?如何定义和使用函数模板?
- 解释默认参数和占位参数的概念,以及它们的使用注意事项。
- 局部变量、全局变量和静态变量的生命周期和作用域分别是怎样的?
- 如何实现递归函数?递归函数有什么优缺点?
- 内联函数的作用是什么?它与普通函数有什么区别?
- 函数指针和成员函数指针有什么区别?如何使用它们?
- 如何实现函数的参数包展开(C++11 及以后)?
- 解释
noexcept
关键字的作用,在什么情况下应该使用它? - 如何实现一个可变参数的函数?
- 函数的返回值类型可以是引用吗?有什么注意事项?
- 静态函数和普通函数有什么区别?静态函数可以访问类的非静态成员吗?
三、面向对象编程(22 题)
- 面向对象编程的三大特性是什么?请分别举例说明。
- 构造函数和析构函数的作用是什么?它们的调用顺序是怎样的?
- 如何实现一个单例模式?单例模式有哪些应用场景?
- 友元函数和友元类的作用是什么?使用友元会带来哪些问题?
- 继承的方式有哪些?它们的区别是什么?
- 如何实现多态?静态多态和动态多态的区别是什么?
- 解释虚析构函数的作用,为什么基类的析构函数通常要声明为虚函数?
- 纯虚函数和抽象类的概念是什么?抽象类有什么作用?
- 如何实现多重继承?多重继承会带来哪些问题?如何解决?
- 拷贝构造函数和赋值运算符重载的作用是什么?什么时候会调用它们?
- 移动构造函数和移动赋值运算符的作用是什么?在什么场景下会使用它们?
- 如何实现一个不可复制的类?
- 如何实现一个可复制但不可移动的类?
- 如何在派生类中调用基类的构造函数和析构函数?
- 如何在派生类中重写基类的虚函数?
override
关键字有什么作用? - 如何在派生类中隐藏基类的成员函数?
- 如何实现一个接口类?接口类和抽象类有什么区别?
- 如何实现一个工厂模式?工厂模式有哪些应用场景?
- 如何实现一个观察者模式?观察者模式有哪些应用场景?
- 如何实现一个策略模式?策略模式有哪些应用场景?
- 虚函数表的实现原理是什么?动态绑定发生在编译期还是运行期?
- 菱形继承的问题如何解决?C++11 的
final
/override
关键字有何作用?
四、内存管理(15 题)
- 栈内存和堆内存的区别是什么?它们的优缺点分别是什么?
- 什么是内存泄漏?如何避免内存泄漏?
- 如何使用智能指针来管理动态内存?
std::unique_ptr
、std::shared_ptr
和std::weak_ptr
的区别是什么? - 解释浅拷贝和深拷贝的概念,在什么情况下需要进行深拷贝?
- 当使用
new[]
分配内存时,应该使用什么来释放内存?为什么? - 如何实现自定义的内存分配器?
- 内存池的概念是什么?在什么场景下会使用内存池?
- 如何检测和调试内存泄漏问题?
- 什么是悬空指针?如何避免悬空指针的产生?
- 如何使用
placement new
?它有什么作用?为什么游戏开发中常使用placement new
? - 解释
std::allocator
的作用和使用方法。 - 如何在 C++ 中实现垃圾回收机制?
- 解释 C++ 的内存模型,以及
std::memory_order
枚举类型的作用。在多线程编程中,如何正确使用内存顺序来避免数据竞争?(附加题) - 内存对齐的作用是什么?如何通过结构体定义优化内存布局?内存对齐对渲染顶点数据有什么影响?
- 为什么
operator new
和operator delete
通常成对重载?
五、STL(10 题)
- STL 包含哪些主要的组件?请简要介绍每个组件的作用。
vector
和deque
的区别是什么?在什么情况下应该使用deque
而不是vector
?map
和set
的底层实现是什么?它们的查找复杂度是多少?- 如何使用迭代器来遍历 STL 容器?迭代器有哪些类型?
list
的特点是什么?在什么场景下适合使用list
?unordered_map
和unordered_set
与map
和set
的区别是什么?它们的适用场景有哪些?- 如何使用 STL 的算法库?请列举几个常用的算法。
std::sort
函数的实现原理是什么?它的时间复杂度是多少?- 如何自定义 STL 容器的比较函数?
- 如何使用 STL 的容器适配器(如
stack
、queue
和priority_queue
)?
六、异常处理与预处理(8 题)
- 如何在 C++ 中进行异常处理?
try
、catch
和throw
关键字的作用是什么? - 异常安全的概念是什么?如何编写异常安全的代码?
- 自定义异常类的步骤是什么?如何使用自定义异常类?
- 预处理指令有哪些?
#define
、#include
和#ifdef
等指令的作用是什么? - 如何使用
#pragma
指令?它有什么作用? - 如何使用
__FILE__
、__LINE__
和__func__
等预定义宏? - 如何使用
#if
、#elif
和#endif
进行条件编译? - 宏定义和函数有什么区别?使用宏定义有哪些优缺点?
七、多线程编程(10 题)
- 如何在 C++ 中创建和管理线程?
std::thread
类的使用方法是什么? - 线程同步的方法有哪些?请简要介绍互斥锁、条件变量和信号量的作用。
- 如何使用
std::mutex
和std::lock_guard
来实现线程同步? - 条件变量的作用是什么?如何使用
std::condition_variable
来实现线程间的通信? - 什么是死锁?如何避免死锁的产生?
- 如何使用
std::async
和std::future
来实现异步编程? - 线程池的概念是什么?如何实现一个简单的线程池?多线程在资源加载系统中如何实现?
- 如何在多线程环境下安全地访问共享资源?
- 解释原子操作(
std::atomic
)的作用和使用方法。在多线程编程中,原子操作和互斥锁有什么区别?游戏中如何选择?(附加题) - 生产者 - 消费者模型中如何实现高效无锁队列?(附加题)
八、C++ 新特性(11 题)
- 解释
std::move
和右值引用的概念,以及它们在 C++ 中的作用。move 语义在游戏对象池中有什么优化作用? lambda
表达式的语法和使用方法是什么?它有哪些捕获方式?默认捕获会带来什么问题?- 如何使用
std::chrono
库来进行时间测量和处理? std::optional
和std::variant
的作用是什么?在什么场景下会使用它们?- 结构化绑定(
structured bindings
)的作用是什么?如何使用它? std::string_view
的作用是什么?它与std::string
有什么区别?- 解释
concepts
(C++20)的作用和使用方法。它对模板编程有什么改进?(附加题) - 如何使用
coroutines
(C++20)来实现异步编程?(附加题) std::format
(C++20)的作用是什么?它与printf
和std::stringstream
有什么区别?(附加题)- 解释
std::span
(C++20)的作用和使用方法。它与数组和指针有什么关系?(附加题) constexpr
和consteval
的区别是什么?在编译期计算中有何应用?
九、模板与泛型编程(7 题)
- 模板特化与偏特化的区别是什么?举例说明游戏开发中的应用场景。模板在游戏配置解析中有哪些应用?
- 什么是 SFINAE?如何利用它实现类型萃取?
- 完美转发(
perfect forwarding
)的实现原理是什么?为什么需要std::forward
? - 模板元编程(TMP)的优缺点有哪些?列举游戏开发中的使用案例。
- 为什么模板类的声明和定义通常放在同一个头文件中?
- 如何实现类型擦除(
type erasure
)?在游戏引擎中的典型应用有哪些? - 如何实现运行时类型识别(RTTI)?游戏引擎是否常用
dynamic_cast
?
十、其他补充(5 题)
volatile
关键字的作用是什么?在游戏开发中何时会用到?- 解释 RAII 机制,列举三个游戏开发中应用 RAII 的例子。
- 什么是零拷贝技术?在 C++ 中如何实现?
emplace_back
与push_back
的区别是什么?为什么优先使用emplace
?- 如何实现线程安全的 STL 容器?
追问示例相关要点提示
- 如果
shared_ptr
管理的对象需要跨线程访问,如何保证线程安全? - 为什么
shared_ptr
的引用计数不是原子操作? - 在游戏中使用
shared_ptr
时需要注意哪些性能问题?