C++ - 为什么在op + =方面实现op +而不是相反?

Enn*_*ael 2 c++ code-reuse operator-overloading

为什么这个实现:

T& T::operator+=( const T& ) {
  // ... implementation ...
  return *this;
}

T operator+( const T& lhs, const T& rhs ) {
  T temp( lhs );
  return temp += rhs;
}
Run Code Online (Sandbox Code Playgroud)

比这更频繁地传播:

T& T::operator+=( const T& rhs ) {
  *this = *this + rhs;
  return *this;
}

T operator+( const T& lhs, const T& rhs ) {
  // ... implementation ...
  return some_result;
}
Run Code Online (Sandbox Code Playgroud)

是否有任何理由,或者只是一个随机的巧合,我看到人们在我阅读的文献中多次这样实现它,而从来没有反过来?

Ben*_*igt 9

operator+必须创建一个新对象来保存结果. operator+=不需要新的对象.

如果你写operator+=的话operator+,你最终会为一个额外的新对象创建,一个赋值(或交换)和一个破坏付出代价,所有这些都是你不需要的.

除此之外,在许多处理器上,硬件具有直接支持+=和类似操作,其中结果存储回输入寄存器之一,而没有用于存储到第三寄存器(如+).

顺便说一句,你的(原始的,现在编辑过的)代码中存在一个错误,它隐藏了部分额外工作.你真的需要:

T& T::operator+=( const T& rhs )
{
    *this = *this + rhs; // creation of temporary, move assignment, and destruction of temporary
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

更糟糕的是,你的(再次原创的,现在编辑过的)建议的实现operator+无法正确返回新对象,而是返回一个悬空引用.这是未定义的行为.


对于那些感兴趣的人,operator+可以通过使用pass-by-value进一步改进第一个实现:

T operator+( T lhs, const T& rhs )
{
    lhs += rhs;
    return lhs;
}
Run Code Online (Sandbox Code Playgroud)

现在如果左手操作数operator+是临时的,将使用移动构造函数,避免复制.虽然使用NRVO,但无论如何都可能在结果代码中没有太大的优势.