为什么不能编写管理 C ++代码中需要管理的编译器(即使其与“CLR兼容”)?
可能有一些妥协,比如在某些情况下禁止 void 指针等。但所有这些额外的关键字等。这些新增内容需要解决的问题是什么?
我对某些方面以及可能难以解决的问题有所了解,但我们将非常感谢一个很好的解释!
答案 0 :(得分:12)
到目前为止,我不得不同意这些答案。
要理解的主要问题是C ++编译器创建的代码适用于非常愚蠢的环境。即使是现代的CPU也不了解虚拟功能,地狱甚至功能都是一个延伸。例如,CPU实际上并不关心用于展开堆栈的异常处理代码是否在任何函数之外。 CPU处理指令序列,具有跳转和返回。就CPU而言,函数当然没有名称。
因此,支持函数概念所需的一切都由编译器放在那里。例如。 vtables只是正确大小的数组,从CPU的角度来看具有正确的值。 __func__
以字符串表中的字节序列结尾,最后一个字节为00.
现在,没有任何内容表明目标环境必须是愚蠢的。你绝对可以定位JVM。同样,编译器必须填写本机提供的内容。没有原始记忆?然后分配一个大字节数组并改为使用它。没有原始指针?只需在整个大字节数组中使用整数索引。
主要问题是C ++程序在托管环境中看起来很难识别。 JVM并不笨,它知道函数,但它希望它们是类成员。它不希望他们的名字中包含<
和>
。你可以规避这一点,但你最终得到的基本上是名称错误。与今天的名称修改不同,这种名称修改不适用于C链接器,而是适用于智能环境。因此,它的反射引擎可能会确信存在具有成员函数c__plus__plus
的类__namespace_std__for_each__arguments_int_pointer_int_pointer_function_address
,这仍然是一个很好的例子。我不想知道如果你有std::map
个字符串来反转迭代器会发生什么。
相反,另一种方式实际上更容易。几乎所有其他语言的抽象都可以用C ++进行按摩。垃圾收集?今天C ++已经允许这样做了,所以你甚至可以支持void*
。
我还没有提到的一件事就是表现。在大字节数组中模拟原始内存?这不会很快,特别是如果你把双打。你可以玩很多技巧来加快速度,但价格是多少?你可能不会得到商业上可行的产品。实际上,您可能会使用一种语言将C ++的最糟糕部分(许多不寻常的依赖于实现的行为)与VM的最差部分(慢)结合起来。
答案 1 :(得分:4)
现有的正确代码,即根据C ++标准编写的代码,不得无意中改变其行为。
答案 2 :(得分:3)
C ++ / CLI主要是托管代码和非托管代码之间的粘合剂。因此,您需要能够混合使用非托管概念。您需要能够在同一代码中分配托管和非托管对象,因此无法绕过单独的关键字。
答案 3 :(得分:3)
为什么不能编译以CLR为目标的本机C ++代码?
是的,你猜对了,会有太多的妥协,这会使它变得毫无用处。我只想举出三个例子......
1。)模板:C ++支持它们,CLR不支持(泛型不同)。 因此,您无法在代码中使用STL,boost等。
2.。)多重继承:C ++支持,而不是CLI。 你甚至无法使用标准的iostream类和衍生物(比如stringstream,fstream),它继承了istream和ostream。
几乎没有任何代码可以编译,你甚至无法实现标准库。
3.)垃圾收集: 大多数C ++应用程序手动管理内存(使用智能指针等),CLR具有自动内存管理功能。 因此,C ++样式“new”和“delete”将与“gcnew”不兼容,使现有的C ++代码对这个新编译器无用。
如果您必须根除所有重要功能,甚至标准库,并且没有现有代码可以编译......那么重点是什么?
答案 4 :(得分:2)
首先,“简单C ++”和“托管C ++”之间的区别是有意的,因为MC ++的目的之一是在现有C ++代码和CLR之间提供桥梁。
接下来,有太多的C ++功能不适合CLR模型。多重继承,模板,指针算术...在编写和运行时,程序员注定要面对神秘的错误,而不是画出明确的界限。
答案 5 :(得分:1)
Qt framework几乎就是这样。即它有智能指针,当它们指向的对象被销毁时自动设置为null。 在经过moc(元对象编译器)解析之后,它仍然是原生C ++。
答案 6 :(得分:1)
我认为这是因为在C ++中添加托管代码功能会使C ++变慢并且编译器更复杂。因此,C ++首先会失去它的设计目标。 C ++的一个好处是,它是一种很好用的语言,它足够低,而且有点便携。也许这就是C ++标准委员会计划让它保持这种状态的原因。无论如何,我认为C ++不能完全“管理”,因为这意味着用C ++编写的程序需要一个VM来执行。如果是这种情况,为什么不使用C ++ / CLI?
答案 7 :(得分:0)
是的,我认为C ++可以被管理。但是,对于C ++而言,.NET需要重写,而不是偏向于BASIC。所有语言都在同一屋檐下。某些功能必须要去。它是VB.NET或C ++ .NET之间的选择,并选择了VB.NET。我听到的有趣的事情是C#比VB.NET更受欢迎(虽然我不使用它!)。
答案 8 :(得分:0)
.NET CLR要求在运行时不知道的任何地方都不能存在对托管对象的引用,除非该对象被固定;良好的性能要求尽可能少地固定物体。由于.NET CLR无法理解C ++中可用的所有数据结构,因此必须在此类结构中不再保留对托管对象的引用。有可能让“普通”C ++代码与.NET代码交互而不需要对C ++语言进行任何更改,但C ++代码可以保留任何.NET对象的任何“引用”的唯一方法就是拥有一些.NET端的代码为每个对象分配某种句柄,并保留与句柄关联的对象的静态表。想要操纵对象的C ++代码必须要求.NET包装器对句柄标识的对象执行某些操作。添加新语法使编译器可以识别.NET框架需要了解的对象类型,并对它们实施必要的限制。
答案 9 :(得分:-1)
首先要考虑的是
使c++
“快”的每件事都会消失。
用c ++完整的垃圾收集系统几乎是不可能的。
因为c++
你几乎可以在代码中的任何地方使用指针。
如果没有直接内置到运行时类型信息会变得昂贵
langauge系统它自己。
你可以利用真正的原生表现。
模板将消失。真正的指针将消失。
直接访问内存已经不见了。
必须强制执行的事项列表
1. no direct pointers(pointers will get replace with complex refernces)
2. templates (generics pay for preformance)
3. simple c-style arrays (will get wrapped with array structures)
4. programmer no longer has control of whether data is on the stack or
the heap.
5. garbage collection will be enforced(this will cause the most changes to the syntax)
6. runtime type data will get added extensively to the code.
(larger code size)
7. inlining will become more difficult for the compiler
(no more inline key word)
8. no more inline assembly.
9. the new langauge by now will become incompatible c code.(unless you go through hoops)
答案 10 :(得分:-1)
我同意5hammer!如果我离开了Java和其他管理语言并非一无所获:那就是完全控制计算机,访问内存自己管理内存,控制计算机如何运行我的代码,与C库集成(如Lua)。 如果我放松了这种灵活性,那么我就会离开C ++并回到C,如果C也被管理,那么我会去汇编。
对于所有游戏平台/复杂程序来说,托管语言是最糟糕的,因为它们将您绑定在一些沙盒中,无法直接访问硬件,并且比编译语言慢得多。
C ++的主要目的始终是Performence。它是大型游戏的最佳语言之一。没有这种语言的表现,很多游戏都不会存在!