掌握 C++ 模板与内存管理,消除代码冗余与内存泄漏
C++ 模板技术通过泛型编程解决同逻辑不同类型的代码冗余问题。函数模板允许编译器根据实参类型自动推导生成具体函数版本,支持隐式和显式实例化两种模式。类模板用于定义通用数据结构如栈,需显式指定类型参数。结合 new/delete 底层内存管理机制,掌握模板能有效提升代码复用性与维护性,避免重复编写相似逻辑,是 C++ 进阶的关键技能。

C++ 模板技术通过泛型编程解决同逻辑不同类型的代码冗余问题。函数模板允许编译器根据实参类型自动推导生成具体函数版本,支持隐式和显式实例化两种模式。类模板用于定义通用数据结构如栈,需显式指定类型参数。结合 new/delete 底层内存管理机制,掌握模板能有效提升代码复用性与维护性,避免重复编写相似逻辑,是 C++ 进阶的关键技能。

实现通用的交换函数。
void Swap(int& left, int& right) {
int temp = left;
left = right;
right = temp;
}
void Swap(double& left, double& right) {
double temp = left;
left = right;
right = temp;
}
void Swap(char& left, char& right) {
char temp = left;
left = right;
right = temp;
}
缺点
模板是一个'代码蓝图',可以根据传入的类型'生成'对应版本的具体代码。
解决'同逻辑、不同类型'的代码冗余问题。
定义一个通用函数,参数类型通过模板参数指定,编译器会根据传入的实参类型自动生成对应版本的函数。
template<typename T>
使用 template 和 typename 来声明模板,这里的 typename 也可以使用 class 来代替,不可以使用 struct。T 是参数类型,可以是内置类型或者自定义类型,可以作为函数的参数或者返回值。
多个类型
template<typename T1, typename T2>
#include <iostream>
using namespace std;
template<typename T> // T 是模板参数,类似于形参,定义的是类型
void Swap(T& x1, T& x2) {
T tmp = x1;
x1 = x2;
x2 = tmp;
}
int main() {
int a = 0, b = 1;
double c = 1.1, d = 2.2;
Swap(a, b);
cout << a << " " << b << endl;
Swap(c, d);
cout << c << " " << d << endl;
return 0;
}
上面的代码中,2 个 Swap 调用的不是同一个函数,编译器通过类型自动推导出函数。
编译器根据参数类型推导出具体函数。
可以直接使用库里面的 swap 模板,库里面的 swap 是小写。
#include <iostream>
using namespace std;
int main() {
int a = 1, b = 2;
cout << a << " " << b << endl;
swap(a, b);
cout << a << " " << b << endl;
return 0;
}
隐式实例化
编译器根据实参推演模板参数的实际类型。
#include <iostream>
using namespace std;
template<class T>
T Add(const T& left, const T& right) {
return left + right;
}
int main() {
int a1 = 10, a2 = 20;
double d1 = 10.1, d2 = 20.2;
cout << Add(a1, d1) << endl;
return 0;
}
代码报错是因为 a1 和 d1 的类型不同,模板参数列表中只有一个 T,编译器无法确定此处到底该将 T 确定为 int 或者 double 类型而报错,在模板中,编译器一般不会进行类型转换操作。下面有两种解决方法。
方法 1
在参数前面添加强制类型转换。
#include <iostream>
using namespace std;
template<class T>
T Add(const T& left, const T& right) {
return left + right;
}
int main() {
int a1 = 10, a2 = 20;
double d1 = 10.1, d2 = 20.2;
cout << Add(a1, (int)d1) << endl;
cout << Add((double)a1, d1) << endl;
return 0;
}
不同的强制类型转换,得到的结果是不一样的。
方法 2
显示类型转换,在函数名后的 <> 中指定模板参数的实际类型。
#include <iostream>
using namespace std;
template<class T>
T Add(const T& left, const T& right) {
return left + right;
}
int main() {
int a1 = 10, a2 = 20;
double d1 = 10.1, d2 = 20.2;
// cout << Add(a1, a2) << endl;
// cout << Add(d1, d2) << endl;
// 强制类型转换
// cout << Add(a1, (int)d1) << endl;
// cout << Add((double)a1, d1) << endl;
// 显示实例化
cout << Add<int>(a1, d2) << endl;
// 隐式类型转换
cout << Add<double>(a1, d2) << endl;
return 0;
}
Add 函数中,使用 const 是因为隐式类型转换会产生临时变量,临时变量具有常性。
特殊情况
有些函数无法自动推导,只能显示实例化。
#include <iostream>
using namespace std;
template<typename T>
T* Alloc(int n) {
return new T[n];
}
int main() {
double* p1 = Alloc<double>(10);
return 0;
}
使用模板来完成的,代码针对广泛的类型。
template<class T1, class T2, ..., class Tn>
class 类模板名 {
// 类内成员定义
};
类模板可以定义多个模版参数。
类模板只能显示实例化,不能传递参数。
#include <iostream>
using namespace std;
template<typename T>
class Stack {
public:
Stack(size_t capacity = 3) {
cout << "Stack(size_t capacity = 3)" << endl;
_array = new T[capacity]; // 只需要个数
_capacity = capacity;
_size = 0;
}
void Push(const T& data) {
_array[_size] = data;
_size++;
}
~Stack() {
cout << "~Stack()" << endl;
if (_array) {
delete[] _array;
_array = NULL;
_capacity = 0;
_size = 0;
}
}
private:
T* _array;
int _capacity;
int _size;
};
int main() {
Stack<int> s1;
// Stack<double> s1;
return 0;
}
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟 <>,然后将实例化的类型放在 <> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
普通类,类名和类型一样,类模板,类名和类型不一样。例如:类名:Stack,类型:Stack。
template< typename T > 的作用范围是下一个函数或者类。
模板的出现,让 C++ 代码摆脱了重复冗余的枷锁,无论是函数模板实现通用逻辑复用,还是类模板构建灵活数据结构,都极大提升了编程效率与代码可维护性。掌握这些知识,就像拿到了 C++ 进阶的密钥,助力我们写出更简洁、更高效、更具扩展性的代码,在编程之路上走得更远、更稳,去探索更广阔的代码天地。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online