C++中Template的用法

模板(Template)

指C++程序设计设计语言中采用类型作为参数的程序设计,支持通用程序设计。C++ 的标准库提供许多有用的函数大多结合了模板的观念,如STL以及IO Stream。

函数模板

函数模板定义一族函数。

//template1.cpp #include <iostream>

template<typename T> void swap(T &a, T &b) {

T tmp{a}; a = b;

b = tmp;

}

int main(int argc, char* argv[])

{

int a = 2; int b = 3;

swap(a, b); // 使用函数模板

std::cout << "a=" << a << ", b=" << b << std::endl;

double c = 1.1; double d = 2.2; swap(c, d);std::cout << "c=" << c << ", d=" << d << std::endl;return 0;

}

函数模板的格式:

template<parameter-list> function-declaration

函数模板在形式上分为两部分:模板、函数。在函数前面加上 template<…>就成为函数模板,因此对函数的各种修饰(inline、constexpr 等)需要加在 function-declaration 上,而不是 template 前。如

template

inline T min(const T &, const T &);

上面 swap 函数模板,使用了类型形参。函数模板就像是一种契约,任何满足该契约的类型都可以做为模板实参。而契约就是函数实现中,模板实参需要支持的各种操作。上面

swap 中 T 需要满足的契约为:支持拷贝构造和赋值。

C++ 的函数模板本质上函数的重载,泛型只是简化了程序员的工作,让这些重载通过编译器来完成

函数模板不是函数

刚才我们提到函数模板用来定义一族函数,而不是一个函数。C++是一种强类型的语

言,在不知道 T 的具体类型前,无法确定 swap 需要占用的栈大小(参数栈,局部变量), 同时也不知道函数体中 T 的各种操作如何实现,无法生成具体的函数。只有当用具体

类型去替换 T 时,才会生成具体函数,该过程叫做函数模板的实例化。当在 main 函数中调用 swap(a,b)时,编译器推断出此时 T 为 int,然后编译器会生成 int 版的 swap 函数供调用。所以相较普通函数,函数模板多了生成具体函数这一步。如果我们只是编

写了函数模板,但不在任何地方使用它(也不显式实例化),则编译器不会为该函数模板生成任何代码。函数模板实例化分为隐式实例化和显式实例化。

隐式实例化

仍以 swap 为例,我们在main 中调用 swap(a,b)时,就发生了隐式实例化(implicit instantiation)。当函数模板被调用,且在之前没有显式实例化时,即发生函数模板的隐式实例化。如果模板实参能从调用的语境中推导,则不需要提供。效率较低。

//template2.cpp #include

template void print(const T &r) {

std::cout << r << std::endl;

}

int main() {

// 隐式实例化print(int) print(1);

// 实例化 print(char) print<>('c');

// 仍然是隐式实例化,我们希望编译器生成print(double) print(1);

return 0;

}

发布了340 篇原创文章 · 获赞 128 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/king9666/article/details/104010754