您的位置:首页 > 其它

使用模板有什么缺点?如何避免?

2012-03-28 23:28 246 查看
文章来源:http://group.gimoo.net/review/82612
templates(模板)是节省时间和避免代码重复的极好方法,我们可以只输入一个类模板,就能让编译器实例化所需要的很多个特定类及函数。类模板的成员函数只有被使用时才会被实例化,所以只有在每一个函数都在实际中被使用时,我们才会得到这些函数。

确实这是一个很重要的技术,但是如果不小心,使用模板可能会导致代码膨胀。什么是代码膨胀?请看下面的例子:

1 template <class T, int num>

2 class A

3 {

4 public:

5 void work()

6 {

7 cout < < "work() " < < endl;

8 cout < < num < < endl;

9 }

10 };

11

12 int main()

13 {

14 A <int, 1>v1;

15 A <int, 2>v2;

16 A <int, 3>v3;

17 A <int, 4>v4;

18 v1.work();

19 v2.work();

20 v3.work();

21 v4.work();

22 return 0;

23 }

类模板A取得一个类型参数T,并且它还有一个类型为int的参数,一个非类型参数(non-type parameter),与类型参数相比,虽然非类型参数不是很通用,但他们是完全合法的。在本例中,由于num的不同,代码14到17行的调用将会生成了三个A的实例,然后在18~21行又生成了不同的函数调用。

虽然这些函数做了相同的事情(打印一个“work()”和num),但他们却有不同的二进制代码。这就是所说的由于模板导致的代码膨胀。也就是说,虽然源代码看上去紧凑而整洁,但是目标代码却臃肿而松散,会严重影响程序的运行效率。

如何避免由于这种代码膨胀呢?有一个原则,就是把C++模板中与参数无关的代码分离出来。也就是让与参数无关的代码只有一份拷贝。对类模板A可以进行如下地修改:

1 template <class T>

2 class Base

3 {

4 public:

5 void work(int num)

6 {

7 cout < < "work ";

8 cout < < num < < endl;

9 }

10 };

11

12 template <class T, int num>

13 class Derived : public Base <T>

14 {

15 public:

16 void work()

17 {

18 Base <T>::work(num);

19 }

20 };

21

22 int main()

23 {

24 Derived <int, 1>d1;

25 Derived <int, 2>d2;

26 Derived <int, 3>d3;

27

28 d1.work();

29 d2.work();

30 d3.work();

31 return 0;

32 }

程序中work的参数版本是在一个Base类(基类)中的。与Derived类一样,Base类也是一个类模板,但是与Derived类不一样的是,它参数化的仅仅是类型T,而没有num。因此,所有持有一个给定类型的Derived将共享一个单一的Base类。比如代码24~26行实例化的模板类都共享Base
<int>模板类,从而他们的成员函数都共享Base <int>模板类中的work这个单一的拷贝。

模板的缺点:不当地使用模板会导致代码膨胀,即二进制代码臃肿而松散,会严重影响程序的运行效率。

解决方法:把C++模板中与参数无关的代码分离出来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: