C++ 模板与泛型编程面试题
1. 什么是模板?模板的作用是什么?
答案:
- 模板定义泛型编程的基础编译时生成具体类型的代码提高代码复用性
- 模板类型函数模板:template<typename T> T max(T a, T b);类模板:template<typename T> class Vector {};变量模板(C++14):template<typename T> T pi = T(3.14);
- 优势类型安全代码复用性能好(编译时展开,无运行时开销)
- 缺点编译时间长代码膨胀错误信息复杂
2. typename和class在模板中的区别?
答案:
- 作为模板参数基本没有区别:template<typename T> 等价于 template<class T>都表示类型参数typename更清晰,推荐使用
- typename的特殊用法指明依赖类型名:typename T::value_type告诉编译器这是一个类型而非变量class不能用于这种场景
- 示例
template<typename T>void func() { typename T::iterator it; // 必须用typename}
3. 模板特化和偏特化是什么?
答案:
- 全特化(Full Specialization)为特定类型提供完全不同的实现所有模板参数都确定
template<typename T>class MyClass { };template<>class MyClass<int> { }; // int的特化版本
- 偏特化(Partial Specialization)部分模板参数特化只有类模板支持偏特化
template<typename T, typename U>class MyClass { };template<typename T>class MyClass<T, int> { }; // U特化为int
- 函数模板只支持全特化,不支持偏特化可以用函数重载代替
- 使用场景为特定类型优化性能处理特殊情况类型萃取(type traits)
4. 什么是SFINAE?
答案:
- 定义Substitution Failure Is Not An Error替换失败不是错误模板参数替换失败时,不报错,而是从候选集中移除
- 应用编译期类型检查条件编译实现type traits
- 示例
template<typename T>typename T::value_type func(T t) { } // 只对有value_type的类型有效template<typename T>T func(T t) { } // 其他类型使用这个版本
- C++11改进enable_ifdecltype更简洁的SFINAE写法
5. 什么是变参模板?
答案:
- 定义C++11引入接受可变数量的模板参数语法:template<typename... Args>
- 参数包展开
template<typename... Args>void print(Args... args) { (cout << ... << args); // C++17折叠表达式}
- 递归展开
template<typename T>void print(T t) { cout << t;}template<typename T, typename... Args>void print(T t, Args... args) { cout << t; print(args...);}
- 应用实现tuple完美转发可变参数函数
6. 什么是完美转发?
答案:
- 定义保持参数的值类别(左值/右值)保持const属性使用std::forward实现
- 实现
template<typename T>void wrapper(T&& arg) { func(std::forward<T>(arg));}
- 万能引用(Universal Reference)T&&在模板中是万能引用可以绑定左值或右值配合std::forward使用
- 应用场景包装函数工厂函数容器的emplace系列函数
7. 模板元编程是什么?
答案:
- 定义在编译期执行的程序使用模板进行计算结果在编译期确定
- 示例:编译期计算阶乘
template<int N>struct Factorial { static const int value = N * Factorial<N-1>::value;};template<>struct Factorial<0> { static const int value = 1;};
- 优势零运行时开销类型安全编译期错误检查
- 缺点编译时间长代码难读错误信息复杂
8. 如何实现类型萃取(Type Traits)?
答案:
- 基本实现
template<typename T>struct is_pointer { static const bool value = false;};template<typename T>struct is_pointer<T*> { static const bool value = true;};
- STL中的type traitsis_integral:是否整数is_floating_point:是否浮点数is_pointer:是否指针is_same:是否相同类型
- 应用编译期类型检查条件编译优化算法选择
- C++11改进标准库提供大量traitsconstexpr简化实现
9. 模板的编译模型是什么?
答案:
- 包含模型模板定义放在头文件每个使用处都实例化可能导致代码膨胀
- 分离模型声明和定义分离使用export关键字(C++11已废弃)实际很少使用
- 显式实例化在cpp文件中显式实例化减少编译时间限制可用类型
- 最佳实践模板定义放头文件复杂模板考虑显式实例化使用extern template减少重复实例化
10. 如何调试模板代码?
答案:
- 编译错误错误信息冗长复杂使用concepts(C++20)改善使用static_assert提供清晰错误
- 调试技巧简化模板参数使用decltype查看类型使用type_traits验证类型
- 工具编译器的模板实例化追踪IDE的类型提示在线工具(如cppinsights.io)
- 最佳实践保持模板简单提供清晰的文档使用static_assert检查约束考虑使用concepts(C++20)
C++面试总结 文章被收录于专栏
本专栏系统梳理C++面试高频考点,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力。