【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
前言
c++模板在编译的时候会被展开,每一个函数或者对象都有自己的静态变量区域,通过一下的代码你就可以看到非常有意思的点.
例子1
#include <iostream> using namespace std; template <typename T> void fun(const T& x) { static int i = 10; cout << ++i; return; } int main() { fun<int>(1); // prints 11 cout << endl; fun<int>(2); // prints 12 cout << endl; fun<double>(1.1); // prints 11 cout << endl; getchar(); return 0; }
输出结果为11 12 11 ,原理很简单,编译期间 fun<int>(1); fun<double>(1.1);会被自动展开为两个函数,通过nm命令查看最后的进程符号也能确定这一点.
0000000000400929 W void fun<double>(double const&)
00000000004008f9 W void fun<int>(int const&)
0000000000600e3c u void fun<double>(double const&)::i
0000000000600e38 u void fun<int>(int const&)::i
模板代码被直接展开了,包括那个静态i值也是两个符号,这就很简单的解释了打印的结果.fun<int>(1);fun<int>(2);操作是void fun<int>(int const&)::i所以就有叠加的效果,而fun<double>(1.1)则则是另外的一个值.
例子2
#include <iostream> using namespace std; template <class T> class Test { private: T val; public: static int count; Test() { count++; } // some other stuff in class }; template<class T> int Test<T>::count = 0; int main() { Test<int> a; // value of count for Test<int> is 1 now Test<int> b; // value of count for Test<int> is 2 now Test<double> c; // value of count for Test<double> is 1 now cout << Test<int>::count << endl; // prints 2 cout << Test<double>::count << endl; //prints 1 getchar(); return 0; }
输出结果为: 2 1
原因和第一个例子一样,只不过这个时候换成类了,通过查看符号信息一样能验证这一点.
总结
c++模板函数或者模板类在编译期间都会被展开根据调用的代码重新变成一个新的符号,这就是所谓的模板推导.这就能解析很多问题,比如模板函数实现写在cpp文件里了,在编译时候可能就找不到符号,因为模板只有在编译器推导才能得出正确的符号,此外大量使用模板函数肯定会导致编译时间变长,进程膨胀.因为模板没遇到一个新的类型的调用都会再推导一次,重新再生成符号,这个过程必然导致时间变长,编译的进程变大.
来源:oschina
链接:https://my.oschina.net/u/3707404/blog/3155164