当前位置: 首页 > 面试题库 >

C ++模板和Java / C#泛型之间的区别是什么?限制是什么?

柏夕
2023-03-14
问题内容

我从这里阅读了一篇有趣的文章/主题/讨论,并且遇到了以下问题:

  • Java / C#泛型的局限性是什么?
  • C ++模板有什么功能,而Java / C#泛型则没有呢?

编辑1 Eric Lippert推荐的其他问题

  • C#泛型可能有哪些模式,而C ++模板却没有?
  • C#的真实泛型类型和Java的类型擦除泛型类型之间有什么区别?

问题答案:

首先,您可能想阅读我在2009年关于该主题的文章。

在我看来,C 模板和C#泛型之间的主要区别在于,C 模板实际上 在构建 模板时就 完全重新编译了代码 。C ++方法的优缺点很多:

  • PRO:您可以有效地创建约束,例如“类型参数T必须具有加法运算符”;如果代码中包含彼此相加的两个T,则如果您使用不允许加法的类型参数构造模板,则模板将无法编译。

  • 缺点:您可能会意外地创建未记录的约束,例如“类型参数T必须具有加法运算符”。

在C#中,您必须 说出 什么约束对用户有帮助,但是您只限于一小部分可能的约束:接口,基类,值与引用类型以及默认构造函数约束,仅此而已。

  • 优点:两种不同结构的语义分析可能完全不同。如果您想要那样,那就太好了。

  • 缺点:对于两种不同的结构,语义分析可能完全不同。如果您不希望那样,那就是一个等待发生的错误。

在C#中,无论构造类型多少次,语义分析都会进行 一次 ,因此需要使用 任何 满足约束的类型实参,而不仅仅是实际提供的类型实参。

  • PRO:您只为需要的构造生成代码。

  • 缺点:您为所有使用的构造生成代码。

模板会导致代码生成变大。在C#中,只生成一次泛型类型的IL,然后在运行时抖动为程序使用的所有类型进行代码生成。这具有很小的性能成本,但是由于抖动实际上对于
所有引用类型参数
仅生成一次代码,因此可以在一定程度上缓解这种情况。因此,如果您有List<object>List<string>则抖动代码仅生成一次,并用于两者。List<int>List<short>由对比度即时编译的代码的两倍。

  • PRO:使用模板库时,您就可以在其中找到源代码。

  • 缺点:要使用模板库,您必须具有源代码。

在C#中,泛型是一流的类型。如果将它们粘贴在库中,则可以在任何地方使用该库而不必附带源代码。

最后:

  • PRO:模板允许模板元编程。

  • 缺点:新手很难理解模板元编程。

  • 缺点:模板系统实际上不允许在通用系统中非常简单的某些类型拓扑。

例如,我想在C ++中很难做到这样:

class D<T> 
{
    class S { }
    D<D<T>.S> ds;
}

在C#泛型中,没问题。在运行时,仅对所有引用类型参数构建 一次 该类型。

但是,在C++模板中,拥有后会发生什么D<int>内部类型构造一个type的字段D<D<int>.S>,因此我们需要构造该类型。但是该类型构造了一个类型为D<D<D<int>.S>.S>…的字段,依此类推直至无穷大。



 类似资料:
  • 问题内容: 我主要使用Java,泛型相对较新。我一直在阅读Java做出了错误的决定,或者.NET具有更好的实现等。 那么,C ++,C#,Java在泛型之间的主要区别是什么?每个优点/缺点? 问题答案: 我将把声音添加到噪音中,并努力使事情变得清晰: C#泛型允许你声明这样的内容。 然后编译器将阻止你将不在Person列表中的内容放入列表中。 在后台,C#编译器只是将其放入.NET dll文件中,

  • 问题内容: Java具有泛型,而通过提供了非常强大的编程模型。那么,和Java泛型之间有什么区别? 问题答案: 它们之间有很大的区别。在C ++中,您不必为泛型类型指定类或接口。这就是为什么您可以创建真正的泛型函数和类,而不必担心键入错误。 上面的方法添加了两个相同类型的对象,并且可以用于具有“ +”运算符的任何类型T。 在Java中,如果要在传递的对象上调用方法,则必须指定一种类型,例如: 在C

  • 本文向大家介绍C和C++的区别是什么?相关面试题,主要包含被问及C和C++的区别是什么?时的应答技巧和注意事项,需要的朋友参考一下 C是面向过程的语言,C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛。 C中函数不能进行重载,C++函数可以重载 C++在C的基础上增添类,C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运

  • 问题内容: 我最近从“高级”开发人员/同事那里得到了一些关于C#垃圾收集器的非常错误的建议,例如… “在C#中,您需要在所有地方使用析构函数,因为不能依赖垃圾收集器。” “不能将C#垃圾收集器视为Java垃圾收集器”。 就我所知,这听起来非常可疑,据我所知,C#和Java垃圾收集器之间的区别如下… C#是分代垃圾收集器,Java是1.6中的并发标记清除,而G1是具有Java 7的新的默认(分代)垃

  • 在Java 7之前,JVM内存中有一个名为PermGen的区域,JVM以前在这里保存它的类。在Java 8中,它被移除并被称为元空间的区域所取代。 PermGen和Metaspace之间最重要的区别是什么? 我知道的唯一区别是,并且忽略了VM参数。

  • 和之间有什么区别? 是什么原因导致他们被扔?如何解决这些问题? 在修改现有代码以包含新的jar文件时,我经常会遇到这些可抛物。我在通过WebStart发布的一个Java应用程序的客户端和服务器端都碰到了它们。 我遇到的可能原因是: 代码客户端的中未包含的包 我们正在使用的新JAR缺少运行时类路径 版本与以前的JAR冲突 当我今天遇到这些问题时,我会采取跟踪和错误的方法来使事情正常工作。我需要更多的