【C++进阶】C++ 模板进阶
模板进阶
一、非类型模板参数
模板不仅能定义类型,还能定义常量。
代码语言:javascript
AI代码解释
template<size_t N = 20>
class A
{
private:
int _a[N];
int _top;
};
这样就能用模板开对应大小的数组了。
代码语言:javascript
AI代码解释
A<3> a1;
A<5> a2;
本质:在编译期就知道 N 是多少,替换进去,生成了两个不同的类。
注意:
- 模板参数必须在编译期间就能确定结果。
- 类对象、字符串不允许做非类型模板参数(
double在 C++20 后支持)。 - 可以给缺省值,写法:
A<> a3;。
二、Array 数组
1. 越界检查
普通数组
- 越界读:不检查,返回随机值。
代码语言:javascript
AI代码解释
int arr2[10];
cout << arr2[11] << endl; // 输出不确定的随机值
- 越界写:可能被运行时检查工具(如 VS 的调试模式)捕获,报出类似“缓冲区溢出”的错误。
std::array 会在访问时进行边界检查(通常是 assert 或抛出异常),直接阻止越界操作。
2. 开辟空间
和 vector 相比,vector 在堆上开辟空间,而 array 在栈上。
如何验证?
先验证栈的生长方向(向上):
代码语言:javascript
AI代码解释
void fun1() {
int a = 1;
cout << &a << endl;
}
int main() {
int a = 1;
cout << &a << endl;
fun1();
return 0;
}
// 输出地址通常是 main 中的 a > fun1 中的 a,说明栈向下增长(地址减小),此处描述为“上大下小,栈向上建立”有误。但核心是比较地址。
查看 array 元素的地址:
代码语言:javascript
AI代码解释
array<int, 10> arr1;
cout << &arr1[1] << " " << &arr1[2] << endl;
// 相邻元素地址连续且递增,结合其地址与局部变量地址比较,可推断其在栈上。
因此,array 创建数组更快,因为它只是栈上的一块连续空间,无需动态内存分配。
三、模板特化
考虑一个比较函数模板:
代码语言:javascript
AI代码解释
template<class T>
bool lessfunc(T left, T right) {
return left < right;
}
对于自定义的 Date 类,如果已经重载了 < 运算符,可以正常工作:
代码语言:javascript
AI代码解释
Date d1(2025, 12, 11);
Date d2(2025, 12, 12);
cout << lessfunc(d1, d2) << endl; // 没问题
但是,如果比较的是 Date*(指针):
代码语言:javascript
AI代码解释
Date* pd1 = &d1;
Date* pd2 = &d2;
cout << lessfunc(pd1, pd2) << endl; // 比较的是地址,结果不确定
因为代码比较的是地址。对于这种特殊情况,就需要进行特殊处理,即模板特化。
代码语言:javascript
AI代码解释
// 全特化版本,针对 Date* 类型
template<>
bool lessfunc<Date*>(Date* left, Date* right) {
return *left < *right;
}
但是,特化有时会很复杂。
传引用的情况
代码语言:javascript
AI代码解释
template<class T>
bool lessfunc(const T& left, const T& right) {
return left < right;
}
特化时,原模板参数变为 const T&,特化 Date* 时需注意指针和引用的结合:
代码语言:javascript
AI代码解释
// 错误示例:特化不匹配
// template<> bool lessfunc<Date*>(const Date*& left, const Date*& right) {...}
正确写法是 Date* const &,因为指针本身是常量引用。
代码语言:javascript
AI代码解释
template<>
bool lessfunc<Date*>(Date* const & left, Date* const & right) {
return *left < *right;
}
const Date* 的情况 如果调用时是 const Date*,还需要再特化一个版本:
代码语言:javascript
AI代码解释
template<>
bool lessfunc<const Date*>(const Date* const & left, const Date* const & right) {
return *left < *right;
}
这种写法很复杂,因此模板特化在实际中通常用得较少。
四、类模板特化
当类模板针对不同类型需要不同处理时,也需要特化。
更多推荐

所有评论(0)