首页 > 代码库 > 为什么要使用泛型?

为什么要使用泛型?

为什么要使用泛型

  通过泛型可以定义类型安全的数据结构(类型安全),而无须使用实际的数据类型(可扩展)。这能够显著提高性能并得到更高质量的代码(高性能),因为您可以重用数据处理算法,而无须复制类型特定的代码(可重用)。在概念上,泛型类似于 C++ 模板,但是在实现和功能方面存在明显差异。

  考虑一种普通的、提供传统 Push() 和 Pop() 方法的数据结构(例如,堆栈)。在开发通用堆栈时,您可能愿意使用它来存储各种类型的实例。您可以使用基于 Object 的堆栈,这意味着,在该堆栈中使用的内部数据类型是难以归类的 Object,并且堆栈方法与 Object 交互:

  

  上述容器可按下述方式使用:

  

  基于 Object 的解决方案存在两个问题。

  第一个问题是性能。在使用值类型时,必须boxing & unboxing。装箱和取消装箱都会根据它们自己的权限造成重大的性能损失,但是它还会增加托管堆上的压力,导致更多的垃圾收集工作,而这对于性能而言也不太好。即使是在使用引用类型而不是值类型时,仍然存在性能损失,这是因为必须从 Object 向您要与之交互的实际类型进行强制类型转换,从而造成强制类型转换开销。

  基于 Object 的解决方案的第二个问题(通常更为严重)是类型安全。因为编译器允许在任何类型和 Object 之间进行强制类型转换,所以您将丢失编译时类型安全。例如,以下代码可以正确编译,但是在运行时将引发无效强制类型转换异常:  

  

  您可以通过提供类型特定的(因而是类型安全的)高性能堆栈来克服上述两个问题。对于整型,可以实现并使用 IntStack。对于字符串,可以实现 StringStack。

  遗憾的是,以这种方式解决性能和类型安全问题,会引起第三个同样严重的问题 — 影响工作效率(无法重用)。编写类型特定的数据结构是一项乏味的、重复性的且易于出错的任务。在修复该数据结构中的缺陷时,您不能只在一个位置修复该缺陷,而必须在实质上是同一数据结构的类型特定的副本所出现的每个位置进行修复。此外,没有办法预知未知的或尚未定义的将来类型的使用情况,因此还必须保持基于 Object 的数据结构。

什么是泛型

  

  在一些 C++ 编译器中,在您通过特定类型使用模板类之前,编译器甚至不会编译模板代码。当您确实指定了类型时,编译器会以内联方式插入代码,并且将每个出现一般类型参数的地方替换为指定的类型。此外,每当您使用特定类型时,编译器都会插入特定于该类型的代码,而不管您是否已经在应用程序中的其他某个位置为模板类指定了该类型。C++ 链接器负责解决该问题,并且并不总是有效。这可能会导致代码膨胀,从而增加加载时间和内存足迹。

一些泛型应用

  

参考:http://msdn.microsoft.com/zh-cn/library/ms379564(VS.80).aspx