- 什么时候使用模板
- 如何创建模板
- 当实例化模板时会发生什么?
- 当使用相同类型实例化模板多次时,会发生什么?
- 延迟实例化
模板(类模板或函数模板)和类或函数很相似。
当你实例化一个模板,你就创建了一个具体的类或函数。
出于习惯,有时也将类模板称为泛型类,将函数模板成为泛型函数。
为了可视化模板实例化的过程,可以使用C++ Insights。
你应该使用模板当函数或类代表了一个抽象的概念,并且不局限于某个特定的类型。
例如:函数max,容器vector都能用于多种类型。
假如有如下函数:
int max(int lhs, int rhs) {
return (lhs > rhs)? lhs : rhs;
}
将其变为一个模板很简单:
- 在函数前面加上
template
- 使用参数T替换具体的类型int。
template // typename 也可以使用 class 代替
T max(T lhs, T rhs) {
return (lhs > rhs)? lhs : rhs;
}
当实例化模板时会发生什么?
使用int
和double
实例化函数模板max:
template
T max(T lhs, T rhs) {
return (lhs > rhs)? lhs : rhs;
}
int main() {
max(10, 5);
max(10.5, 5.5);
}
C++ Insights显示了模板实例化的具体过程:
template
T max(T lhs, T rhs) {
return (lhs > rhs)? lhs : rhs;
}
/* First instantiated from: insights.cpp:8 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
int max(int lhs, int rhs)
{
return (lhs > rhs) ? lhs : rhs;
}
#endif
/* First instantiated from: insights.cpp:9 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
double max(double lhs, double rhs)
{
return (lhs > rhs) ? lhs : rhs;
}
#endif
int main()
{
max(10, 5);
max(10.5, 5.5);
return 0;
}
可以看到编译器分别为int
和double
生成了特化的函数。
下面是一个类模板的例子。
template
class Array{
public:
int getSize() const{
return N;
}
private:
T elem[N];
};
int main() {
Array myArr1; // (1)
Array myArr2; // (2)
Array myArr3; // (3)
}
Array
实例化了2次,Array
实例化了一次。
C++ Insights的主要输出如下:
template
class Array{
public:
int getSize() const{
return N;
}
private:
T elem[N];
};
/* First instantiated from: insights.cpp:13 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Array
{
public:
inline int getSize() const;
private:
int elem[5];
public:
// inline Array() noexcept = default;
};
#endif
/* First instantiated from: insights.cpp:14 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Array
{
public:
inline int getSize() const;
private:
int elem[10];
public:
// inline Array() noexcept = default;
};
#endif
可以看到,第二次实例化(3)Array
使用了第一次实例化的代码。
有2个有趣的发现:1. 模板实例化是延迟(lazy)的; 2. 可以使用非类型作为模板参数。
从上面输出可以看到成员函数getSize()
没有实例化,仅有声明。
这个意味着如果没有使用将不会被实例化。
修改代码如下:
int main() {
Array myArr1;
Array myArr2;
Array myArr3;
myArr3.getSize(); // (1)
}
编译器将会生成getSize
的代码:
...
/* First instantiated from: insights.cpp:13 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Array
{
public:
inline int getSize() const
{
return 5;
}
private:
int elem[5];
public:
// inline Array() noexcept = default;
};
#endif
...
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)