【问题标题】:C# generics compared to C++ templates [duplicate]C# 泛型与 C++ 模板的比较 [重复]
【发布时间】:2010-11-15 12:59:48
【问题描述】:

可能重复:
What are the differences between Generics in C# and Java… and Templates in C++?

C# 泛型与 C++ 模板相比有何不同?我知道他们解决的问题并不完全相同,那么两者的优缺点是什么?

【问题讨论】:

标签: c# c++ generics templates comparison


【解决方案1】:

您可以将 C++ 模板视为一种伪装成泛型系统的解释型函数式编程语言。如果这不吓到你,它应该:)

C# 泛型非常受限;您可以在一个或多个类型上参数化一个类,并在方法中使用这些类型。因此,以MSDN 为例,您可以这样做:

public class Stack<T>
{
   T[] m_Items; 
   public void Push(T item)
   {...}
   public T Pop()
   {...}
}

现在您可以声明Stack&lt;int&gt;Stack&lt;SomeObject&gt;,它会安全地存储该类型的对象(即,不用担心错误地输入SomeOtherObject)。

在内部,.NET 运行时会将其专门化为 int 等基本类型的变体和对象类型的变体。例如,这允许Stack&lt;byte&gt; 的表示比Stack&lt;SomeObject&gt; 的表示小得多。

C++ 模板允许类似的用途:

template<typename T>
class Stack
{
    T *m_Items;
    public void Push(const T &item)
    {...}
    public T Pop()
    {...}
};

乍一看,这看起来很相似,但有一些重要的区别。首先,不是每个基本类型都有一个变体,而所有对象类型都有一个变体,每个实例化的类型都有一个变体。那可以是很多类型!

下一个主要区别是(在大多数 C++ 编译器上)它将在使用它的每个翻译单元中编译。这会大大减慢编译速度。

C++ 模板的另一个有趣的属性是它们可以应用于类以外的东西——当它们被应用时,它们的参数可以被自动检测到。例如:

template<typename T>
T min(const T &a, const T &b) {
  return a > b ? b : a;
}

类型 T 将由函数使用的上下文自动确定。

这些属性可以用来取得好成绩,但会牺牲你的理智。因为 C++ 模板针对它所针对的每种类型重新编译,并且模板的实现始终可供编译器使用,所以 C++ 可以对模板进行非常积极的内联。再加上函数中模板值的自动检测,您可以在 C++ 中使用boost::lambda 生成anonymous pseudo-functions。因此,像这样的表达式:

_1 + _2 + _3

产生一个具有 严重可怕 类型的对象,它有一个 operator() 将其参数相加。

C++ 模板系统还有很多其他的阴暗角落——它是一个非常强大的工具,但考虑起来可能会很痛苦,而且有时很难使用——尤其是当它给你一个长达 20 页的错误消息时。 C# 系统要简单得多 - 功能较弱,但更易于理解且更难滥用。

【讨论】:

  • C++ 模板的另一个有趣属性是它们可以应用于类以外的东西 - 这与 C# 允许我们在函数中定义泛型是否相同(例如 @987654332 @) ?
  • C++ 模板将执行得更快,因为它们在 C++ 中编译为机器代码(可能是因为它们是编译器宏,而不是过于通用)。但 C# 对象不必重新编译就可以放入 dll 中。如果您正在开发允许动态代码执行的程序,则可以使用在运行时插入的 C# 泛型对象或函数,而无需重新编译。我相信这个技巧在 C++ 中会更难实现,因为它的模板化函数或东西必须被编译以获得它们的不同实例。
【解决方案2】:

http://blogs.msdn.com/csharpfaq/archive/2004/03/12/88913.aspx

大致上,大部分区别与模板在编译时解析,而泛型在运行时解析这一事实有关。

【讨论】:

  • 实际上,虽然泛型可以在运行时实例化(通过反射,就像其他任何东西一样),但很多东西都是在编译时计算出来的。例如,JIT 生成 List&lt;int&gt; 的特定实现,而不是使用等同于 List&lt;object&gt; 的通用类型擦除版本(这是它与 Java 不同的一个方式)。
  • @Earwicker:告诉我。这就是为什么您不能进行通用提升(即将 List 连接到 List)的原因。该功能存在于 CLI 中,但他们选择不在 C# 中以这种方式实现它(一个错误,IMO)。
【解决方案3】:

【讨论】:

  • 看起来这个问题是重复的。谢谢指点。
【解决方案4】:

blog entry from Eric Gunnerson 很好地涵盖了这个主题。

最大的直接区别是模板是编译时特性,而泛型是运行时特性。

【讨论】:

    【解决方案5】:

    这看起来像是一个方便的参考。

    http://msdn.microsoft.com/en-us/library/c6cyy67b.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多