9

为什么不能编写一个编译器来管理需要在 C++ 代码中管理的内容(即使其“与 CLR 兼容”)?

也许有一些妥协,比如禁止无效指针等。但是所有这些额外的关键字等。这些添加必须解决的问题是什么?

我对某些方面以及可能难以解决的问题有自己的想法,但我们将不胜感激!

4

11 回答 11

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 的最糟糕的部分(慢)结合在一起的语言。

于 2009-05-04T13:00:37.870 回答
4

现有的正确代码,即根据 C++ 标准编写的代码,不得无意中改变其行为。

于 2009-05-04T09:25:59.320 回答
3

好吧,C++/CLI 主要是托管和非托管代码之间的粘合剂。因此,您需要能够混合托管和非托管概念。您需要能够在同一代码中分配托管对象和非托管对象,因此无法绕过单独的关键字。

于 2009-05-04T10:40:16.630 回答
3

为什么不能编译针对 CLR 的本机 C++ 代码?

是的,你猜对了,会有太多的妥协,那会让它变得毫无用处。我只想举三个例子...

1.) 模板:C++ 支持它们,CLR 不支持(泛型不同)。所以你不能在你的代码中使用 STL、boost 等。

2.) 多重继承:在 C++ 中支持,在 CLI 中不支持。您甚至不能使用从 istream 和 ostream 继承的标准 iostream 类和派生类(如 stringstream、fstream)。

几乎没有任何代码可以编译,您甚至无法实现标准库。

3.) 垃圾收集:大多数 C++ 应用程序手动管理它们的内存(使用智能指针等),CLR 具有自动内存管理。因此,C++ 风格的“new”和“delete”将与“gcnew”不兼容,使得现有的 C++ 代码对这个新编译器毫无用处。

如果你必须根除所有重要的特性,甚至是标准库,并且没有现有的代码可以编译......那有什么意义呢?

于 2009-05-04T11:11:45.557 回答
2

首先,“简单 C++”和“托管 C++”之间的区别是有意的,因为 MC++ 的目的之一是在现有 C++ 代码和 CLR 之间架起一座桥梁。

其次,有太多的 C++ 特性不适合 CLR 模型。多重继承、模板、指针算法......如果没有明确的界限,程序员将注定要在编译和运行时面临神秘的错误。

于 2009-05-04T11:03:22.537 回答
1

Qt 框架几乎可以做到这一点。即它有智能指针,当它们指向的对象被销毁时,它会自动设置为空。经过 moc(元对象编译器)解析后,它仍然是原生 C++。

于 2009-05-04T09:33:20.007 回答
1

我认为这是因为将托管代码功能添加到 C++ 中会使 C++ 变慢并且编译器更复杂。如此之多以至于 C++ 会失去它最初的设计目的。C++ 的优点之一是它是一种很好的语言,它足够低级并且具有一定的可移植性。可能这就是 C++ 标准委员会计划让它保持这种状态的原因。无论如何,我不认为 C++ 可以被完全“管理”,因为这意味着用 C++ 编写的程序需要一个虚拟机来执行。如果是这样,为什么不直接使用 C++/CLI?

于 2009-05-04T10:16:09.637 回答
0

是的,我想 C++ 可以被管理。但是,.NET 需要为 C++重写,而不是偏向于 BASIC。在同一个屋檐下拥有多种语言。某些功能必须取消。在VB.NET或C++.NET之间进行选择,最终选择了VB.NET。我听到的有趣的事情是 C# 比 VB.NET 更流行(尽管我都没有使用!)。

于 2012-04-19T08:09:41.517 回答
0

.NET CLR 要求在运行时不知道的任何地方都不能存在对托管对象的引用,除非对象被固定;良好的性能要求尽可能少地固定对象。由于 .NET CLR 无法理解 C++ 中可用的所有数据结构,因此对托管对象的引用必须永远不会保留在此类结构中。可以让“普通”C++ 代码与 .NET 代码交互,而无需对 C++ 语言进行任何更改,但 C++ 代码可以保持对任何 .NET 对象的任何“引用”的唯一方法是拥有一些.NET 端的代码为每个对象分配某种句柄,并保留与句柄关联的对象的静态表。然后,想要操作对象的 C++ 代码必须要求 .NET 包装器对由句柄标识的对象执行一些操作。添加新语法使编译器能够识别 .NET 框架需要了解的对象类型,并对它们实施必要的限制。

于 2013-10-01T21:29:37.390 回答
-1

首先要考虑的是一切使c++“快”的东西都会消失。一个完整的 C++ 垃圾收集系统几乎是不可能的。因为c++您几乎可以在代码中的任何位置使用指针。如果不直接将运行时类型信息内置到它自己的语言系统中,那么运行时类型信息就会变得昂贵。您可以利用真正的原生性能。模板将消失。真正的指针会消失。直接访问内存已不复存在。

必须执行的事情清单

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) 
于 2015-05-04T21:52:44.200 回答
-1

我同意5hammer!如果我离开 Java 和其他托管语言,这不是没有意义的:那就是完全控制计算机,自己访问内存管理内存,控制计算机如何运行我的代码,与 C 库(例如 Lua)集成。如果我失去了这种灵活性,那么我会离开 C++ 并退回到 C,如果 C 也成为托管的,那么我会去汇编程序。

托管语言是所有游戏平台/复杂程序中最糟糕的语言,因为它们将您限制在某种沙箱中,无法直接访问硬件,并且比编译语言慢得多。

C++ 的主要目的一直是性能。它是大型游戏的最佳语言之一。如果没有这种语言表演,很多游戏都不会存在!

于 2016-04-06T13:42:08.163 回答