【问题标题】:What is the best signature for overloaded arithmetic operators in C++?C++ 中重载算术运算符的最佳签名是什么?
【发布时间】:2008-09-23 01:29:26
【问题描述】:

我曾假设 operator+ 的规范形式,假设存在重载的 operator+= 成员函数,是这样的:

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs) +=rhs;
}

但有人向我指出,这也可以:

const T operator+ (T lhs, const T& rhs)
{
    return lhs+=rhs;
}

本质上,这种形式将临时的创建从实现主体转移到函数调用。

这两个参数有不同的类型似乎有点别扭,但是第二种形式有什么问题吗?有理由偏爱一个吗?

【问题讨论】:

    标签: c++ operator-keyword


    【解决方案1】:

    我不确定两者生成的代码是否有很大差异。

    在这两者之间,我(个人)更喜欢第一种形式,因为它更好地传达了意图。这是关于您对 += 运算符的重用和通过 const& 传递模板化类型的习惯用法。

    【讨论】:

      【解决方案2】:

      对于已编辑的问题,首选第一种形式。编译器更有可能优化返回值(您可以通过在 T 的构造函数中放置断点来验证这一点)。第一种形式也将两个参数都取为 const,这样会更可取。

      返回值优化课题的研究,比如这个链接作为一个简单的例子:http://www.cs.cmu.edu/~gilpin/c++/performance.html

      【讨论】:

      • 不一定。大多数现代编译器会检测到只需要一个副本并将其优化掉。
      • (以上是@Kris,但实际上也适用于@Corey。)
      • Corey:参见 Scott Meyer 的《更有效的 C++》,第 20 条。
      • @Kris K。我回家后会查一下。
      • 我最近与编译器合作过,当它们确实支持优化时,您必须确保它已打开。
      【解决方案3】:

      为了便于阅读,我更喜欢第一种形式。

      在看到第一个参数被复制之前,我不得不三思而后行。我没想到会这样。因此,由于这两个版本可能都一样高效,我会选择一个更易于阅读的版本。

      【讨论】:

      • 同上。我盯着第二个例子想知道它怎么可能是等价的,然后我看到它没有通过引用传递。第一个版本更清晰。
      【解决方案4】:
      const T operator+(const T& lhs, const T& rhs)
      {
          return T(lhs)+=rhs;
      }
      

      如果你想要简洁,为什么不这样做呢?

      【讨论】:

      • 谢谢——这是迈尔斯书中的内容,用来消除临时性——我已经调整了。
      【解决方案5】:

      我的第一个想法是第二个版本可能比第一个版本快得多,因为没有将引用作为参数压入堆栈。但是,这将非常依赖于编译器,例如取决于编译器是否执行命名返回值优化。

      无论如何,如果有任何疑问,切勿选择可能不存在且您很可能不需要的非常小的性能提升 - 选择最清晰的版本,这是第一个。

      【讨论】:

        【解决方案6】:

        其实还是首选第二种。正如 c++ 标准中所述,

        3.7.2/2:自动存储时长

        如果一个命名的自动对象有 初始化或析构函数 副作用,不应该 在其区块结束之前被摧毁, 也不应作为一种被淘汰 优化,即使它看起来是 未使用,除了一个类对象或 它的副本可能会被删除 在 12.8 中指定。

        也就是说,由于使用复制构造函数创建了一个未命名的临时对象,编译器可能不会使用返回值优化。然而,对于第二种情况,未命名的返回值优化是允许的。请注意,如果您的编译器实现了命名返回值优化,那么最好的代码是

        const T operator+(const T& lhs, const T& rhs)
        {
            T temp(lhs);
            temp +=rhs;
            return temp;
        }
        

        【讨论】:

          【解决方案7】:

          我认为,如果您将它们都内联(我会,因为它们只是转发函数,并且大概 operator+=() 函数是离线的),您将获得几乎无法区分的代码生成。也就是说,第一个更规范。第二个版本是不必要的“可爱”。

          【讨论】:

          • 哇 - 不知道这个问题有多老 - 希望你仍然感兴趣! :)
          猜你喜欢
          • 2016-09-27
          • 1970-01-01
          • 2020-03-10
          • 1970-01-01
          • 1970-01-01
          • 2012-07-05
          • 2010-10-19
          • 2023-03-07
          相关资源
          最近更新 更多