【问题标题】:What is the performance penalty of operator overloading STL运算符重载 STL 的性能损失是什么
【发布时间】:2010-12-20 12:02:45
【问题描述】:

我非常喜欢 STL。它使编码算法变得非常方便,因为它为您提供了所有的原语,如 parition、find、binary_search、iterators、priority_queue 等。另外,您根本不必担心内存泄漏。

我唯一担心的是 STL 工作所必需的运算符重载的性能损失。 为了比较,我认为它依赖于 == 提供所需的语义。如果我们要将类添加到容器中,我们需要重载 ==operator。

为了方便,我损失了多少效率?

另一个关于内存泄漏的问题:

  1. 使用 STL 容器时会发生内存泄漏吗?
  2. 在 Java 中会发生内存泄漏吗?

【问题讨论】:

  • 当然,Java 中可能会发生内存泄漏 - 请参阅此处:ibm.com/developerworks/library/j-leaks
  • 重载的运算符基本上是一种方法。
  • 不错的链接@schnaader。希望我能给你一个 +1 的 cmets。
  • @ajay 将来我会把这样的事情分成两个问题。你这篇文章的标题与你关于 Java 和内存泄漏的问题无关。
  • 您为什么认为运算符重载会导致性能下降?我对此感到困惑。另外,标准问题:你确定你有性能问题吗?检查您的测量结果。探查器说问题出在哪里?你的基线表现是什么,你的目标是什么,你的衡量计划是什么?我们对这里的这些部分中的微优化器没有太多了解。

标签: java c++ stl memory-leaks


【解决方案1】:

在泛型类型上使用 stl 算法时,您必须以某种方式提供比较逻辑。运算符重载对任何其他函数没有性能损失,并且可以(像任何其他函数一样)内联以消除任何函数调用开销。

许多标准容器和算法也使用std::less,因此默认使用<而不是==

标准容器本身不会泄漏,但您可以使用它们来保存不一定会清理它们“拥有”的内存的对象(例如指针)。

在java中内存泄漏是很困难的,但这并不意味着你不会因为没有良好的对象所有权语义而陷入困境,这并不意味着你不能用尽所有可用的内存和崩溃。

【讨论】:

    【解决方案2】:

    我会把 C++ 的答案留给之前的海报,但是 100% 是的,你可以在 Java 中发生内存泄漏。除非您有一些好的内存分析工具可供查看,否则它往往也很难找到。通常,当您重复实例化对象时,自动垃圾收集语言(例如 Java、Python 等)中的内存泄漏会发生,但是 A. 当您完成它们时不要清理它们(例如在一个数据库连接)或 B. 继续持久化指向它们的其他对象(例如 Hashtables),以便自动垃圾收集器永远不会对它们进行垃圾收集。

    如果您的应用程序处于您认为应该处于稳定状态的状态,并且您会获得以下状态之一:

    http://java.sun.com/javase/6/docs/api/java/lang/OutOfMemoryError.html

    你在进行一些有趣的调试;)

    【讨论】:

    • 也许这太过分了 C++,但如果内存被应用程序中仍然有引用的对象使用,这真的是内存泄漏吗?在这种情况下,仍然可以(理论上)从应用程序中的对象中找到内存。 “真正的”内存泄漏是对某些内存的最后引用实际上已被销毁,因此应用程序中根本没有指向内存的指针。
    • 我认为使用自动垃圾收集的语言的定义会发生一些变化......对我来说,其中一种语言的内存泄漏是程序员为防止垃圾收集器清理引用而做的任何事情程序员完成并期望被垃圾收集的对象。自动垃圾收集器足够聪明,可以清理不再有任何其他对象引用它们的对象。要在 Java 中持久存在内存中,仍然必须有对周围对象的活动引用。
    【解决方案3】:

    由于运算符重载只会导致函数调用,而且无论如何您都必须编写一个函数来完成这项工作,因此开销为零。运算符重载只是一种方便,因此您可以执行诸如 x == y 代替 x.equals(y) 或 x

    【讨论】:

      【解决方案4】:

      “惩罚”实际上是一种奖金。

      让我们来看看最典型的算法,排序。 C 没有运算符重载。因此,qsort 采用函数指针。每个比较都使用间接函数调用(在运行时)。 C++ 确实有运算符重载。对于std::sort,每个比较都是直接调用(由链接器修复)或内联(由编译器)。这是非常有效的。 std::sortqsort 快​​ 6 倍的情况并不少见。

      一般来说,操作符重载可以更容易地表达一个类型的“默认”函数,这种方式可以被其他代码和编译器利用。替代方案的效率要低得多。它们要么依赖宏(这会伤害程序员),要么依赖函数指针(这会伤害优化器和 CPU。)

      【讨论】:

        【解决方案5】:

        我唯一担心的是 STL 工作所必需的运算符重载的性能损失。为了比较,我认为它依赖于 == 提供所需的语义。如果我们要将类添加到容器中,我们需要重载 ==operator。

        这是不存在的。您的重载运算符被实现为函数调用。而且,如果您没有重载运算符,则需要定义一个要使用的函数。所以性能完全相同相同,只是语法更简洁。

        【讨论】:

          【解决方案6】:

          What is the performance penalty of operator overloading STL

          除此之外,您始终可以让您的运算符内联,这甚至不会受到函数调用的影响。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-05-06
            • 2015-11-13
            • 1970-01-01
            • 1970-01-01
            • 2010-12-01
            • 2015-06-23
            • 2013-07-30
            相关资源
            最近更新 更多