【问题标题】:C++ corrupt my thinking, how to trust auto garbage collector?C++ 破坏了我的思维,如何信任自动垃圾收集器?
【发布时间】:2010-06-06 07:12:40
【问题描述】:

我过去主要使用 C/C++ 进行编程,这让我每天都在处理指针和内存管理。这几天我正在尝试使用其他工具进行开发,例如 Java、Python 和 Ruby。

问题是我一直在思考 C++ 风格,我编写的代码几乎都是用几乎所有编程语言编写的 C++,而最大的问题是内存管理,我一直在使用 Java 中的引用编写糟糕的代码,然后得到尽可能接近 C++ 风格。

所以我需要 2 点思考,一个是信任垃圾收集器,假设通过查看基准和证明它确实在 Java 中运行,并且知道我不应该做什么才能让我的代码以最好的方式是。

第二个想法是知道如何编写其他语言代码。我的意思是我知道该怎么做,我只是从来没有像大多数 Java 或 Python 程序员通常做的那样编写代码,是否有任何 C++ 程序员的书只是为了向我介绍编写约定? (顺便说一句,请原谅我的英语错误)

【问题讨论】:

  • 如果垃圾收集器不起作用,Java 或 C# 会流行起来吗?
  • 你的代码到底是什么意思?
  • 我写C++风格的代码,为我的队友抱怨。他们说我必须了解语言约定,并使用它而不是我从 C++ 经验中带来的约定。我正在寻找的是一些指南,它将解释 C++ 程序员如何用 Java 或任何其他语言编写好的代码。

标签: java c++ memory-management


【解决方案1】:

对内存使用和常见泄漏有良好的直觉在 Java 中也是一件好事。在 Java 中内存泄漏是不可能的,这是一个常见的误解

忽略仔细的内存管理的人,例如,很快就会得到大量悬空的 GUI 组件树,可以从长寿命模型中的侦听器列表中访问。 (去过那里,做到了。)

继续结构化地编写代码,不要“利用”你可以偷懒的事实。

另一个误解是垃圾收集器“慢”。这些算法非常有效,在你分析你的程序之前你不应该担心它。一个很好的工具是 JVisualVM(与 JDK 捆绑在一起)。该工具将向您显示 CPU 分析,并可以帮助您解决可能的内存泄漏并跟踪不必要的小型临时分配。

【讨论】:

    【解决方案2】:

    要记住的一个区别是,在 C++ 中,析构函数可用于清理任何类型的资源,而不仅仅是内存(即RAII)。在 Java 中,您必须在 try - finally 块中显式关闭文件、套接字、数据存储连接等。如果将资源清理代码放在 Java 的 finalize 方法中,那么它可能会在未来某个不确定的时间被调用,或者永远不会被调用,因此不推荐。所以在某些方面,这给程序员带来了更大的负担,而不是更少。

    Python 介于两者之间 - 您可以使用“with”语句来处理大多数资源的自动清理。

    C++ 内存管理的两个问题是内存泄漏和试图使用已经被销毁的对象。正如其他人指出的那样,如果您保留对不再需要的对象的引用,那么在 Java(和 Python)中也会出现内存泄漏,而该对象又可能引用了其他对象。 Java 中的内存泄漏可能不那么频繁,但是当它们确实发生时,它们可能比 C++ 中的要大得多。明智地使用弱引用会有所帮助,并将 null 分配给不再需要的变量。然而,这会导致第二个问题——如果您尝试使用该变量,您将获得 NullPointerException。这比您在 C++ 中可能遇到的分段错误更有帮助,但仍然是一个问题。

    因此,您在 C++ 中学到的有关内存管理的所有内容仍然适用于 Java,但您也必须为其他资源这样做。

    【讨论】:

    • 你不能使用 finalizes 来关闭文件和东西吗?
    • @AndrejaKo - 我写了关于 finalize 的文章,但错误地将其输入为“finally” - 现在已更正。出于上述原因,要回答您的问题,不,您不能。
    • @AndrejaKo - 不,最终确定是不确定的,您可以通过这种方式轻松耗尽资源。
    【解决方案3】:

    我想我完全理解你的心态问题,主要是因为我有完全的相反:)

    我的建议是尝试创建一种从 C++ 到 Java 的范式转换,使自己能够编写更多实际代码,而不是自己管理对象。

    举一个具体的例子,我假设在 C++ 中,你在对象生命周期的开始和结束时会做一些事情,这意味着你很可能应该将这些事情包装到它们自己的方法中(不是构造函数/析构函数,请注意!)首先要“训练”自己在 C++ 中显式使用它们。然后,当迁移到 Java 时,您实际上可以根据您的其他编程习惯很容易地超越这种方法类比,而不是用析构函数之类的东西挠头,只需实现这些方法的基础,但将它们留空。通过这种方式,您为您自己拥有了一个不那么隐形的心理标记,表明对象生命周期即将结束,最终当您学会相信它时,您可以将其移除。您甚至不必担心开销,只要方法体为空,JVM 就会优化掉那些多余的方法调用。

    当然,下一步是将其扩展到原始值,并从对象生命周期进一步扩展到方法粒度级别。为了真正浓缩我的意思,这是一个应用了这些心理助手的示例类:

    public class MentalHelpers {
        private MyFieldObject mfo;
    
        /**
         * Note the separate method for object creation.
         * This is actually good practice in general!
         */
        public MentalHelpers() {
            createObject();
        }
    
        private final void createObject() {
            mfo = new MyFieldObject();
        }
    
        private final void destroyObject() {
            // Do nothing! private or public, you decide.
        }
    
        public int incrementOne() {
            int i = 1;
    
            int ret = i++;
    
            freeInt(i);
    
            return ret;
        }
    
        private final freeInt(int i) {
            // Once again, do nothing!
        }
    }
    

    就是这样,希望对您有所帮助。

    【讨论】:

    • 为什么使用不同的方法来创建对象是个好习惯?我看不出它有什么不好的原因,但为什么它会好,除非您使用需要设置的非内存资源?
    • @AndrejaKo:在构造只能部分模拟的部分/复杂对象时,允许更轻松的依赖注入和覆盖(尤其是在测试中,为什么在扩展时也不这样做) .
    【解决方案4】:

    打开垃圾收集日志并在GCViewer 中查看结果。这将向您展示您的应用程序中的内存是如何执行的,以及当垃圾收集器运行时是否有足够的内存被清理。


    (来源:tagtraum.com

    【讨论】:

    • 在 Java 1.5 及更高版本中,jconsole 提供相同(或相似)的信息而不需要 GC 日志记录,并且可以连接到正在运行的 Java 进程
    【解决方案5】:

    我认为你应该继续思考 C++ 风格。 Java 中的对象创建成本很高,比 C++ 中的成本更高,因为您没有在堆栈上分配的选项。不过,不确定这是否是您正在寻找的答案。

    【讨论】:

    • 也不确定这是否有意义;)
    • 现代 JVM 将尽可能自动在堆栈上分配 - ibm.com/developerworks/java/library/j-jtp09275.html 事实上,由于“智能”分配/内联,Java 中的对象分配通常更便宜。
    • 在 Java 中创建对象并不昂贵。以前是这样,但现在 JVM 使用了分代 GC,这很有帮助。 ibm.com/developerworks/java/library/j-jtp01274.html
    • 如今在 Java 中创建对象需要 2 或 3 条指令,这使得它比古老的 i++ 示例更轻量级。
    • 但是对于 C++ 中的短期对象,编译器完全消除了构造,并为其成员变量使用寄存器,因此成本为零。因此,在 C++ 中使用临时结构作为函子作为算法的参数是很常见的。在 Java 中创建任何使用的对象都会有很小的开销,而且由于它仅限于运行时多态性,因此对何时可以内联函数调用有更多限制。
    猜你喜欢
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    相关资源
    最近更新 更多