【问题标题】:Why does C++ need language modifications to be "managed"?为什么 C++ 需要“管理”语言修改?
【发布时间】:2010-10-23 14:17:55
【问题描述】:

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

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

我对某些方面以及可能难以解决的问题有自己的想法,但我们将非常感谢您提供可靠的解释!

【问题讨论】:

    标签: c++ .net c++-cli clr managed-code


    【解决方案1】:

    到目前为止,我不得不不同意这些答案。

    要理解的主要问题是 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 的最糟糕的部分(慢)结合在一起的语言。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

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

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

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

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

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

          如果您必须根除所有重要功能,甚至是标准库,并且没有现有代码可以编译...那还有什么意义?

          【讨论】:

          • 模板纯粹是一个编译时构造。与泛型不同,它们不需要任何运行时支持。
          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                【解决方案8】:

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

                【讨论】:

                  【解决方案9】:

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

                  【讨论】:

                    【解决方案10】:

                    首先要考虑的是 使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) 
                    

                    【讨论】:

                      【解决方案11】:

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

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

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

                      【讨论】:

                        猜你喜欢
                        • 2011-04-22
                        • 2011-10-05
                        • 2011-05-15
                        • 2015-04-26
                        • 2019-05-15
                        • 1970-01-01
                        • 2013-09-28
                        • 2019-02-19
                        • 1970-01-01
                        相关资源
                        最近更新 更多