为什么C++中重载二进制算子运算符的规范实现要按值传递第一个参数?

问题描述 投票:3回答:1

根据 此cppreference页,通过值传递重载二进制运算符的第一个参数,以某种方式优化了表达式,如 a + b + c. 链接页面的相关代码片段如下。

class X
{
 public:
  X& operator+=(const X& rhs)         // compound assignment (does not need to be a member,
  {                                   // but often is, to modify the private members)
    /* addition of rhs to *this takes place here */
    return *this;                     // return the result by reference
  }

  // friends defined inside class body are inline and are hidden from non-ADL lookup
  friend X operator+(X lhs,           // passing lhs by value helps optimize chained a+b+c
                     const X& rhs)    // otherwise, both parameters may be const references
  {
    lhs += rhs;                       // reuse compound assignment
    return lhs;                       // return the result by value (uses move constructor)
  }
};

我有两个问题

  1. 链条上的... a + b + c 表达式经此优化?
  2. 假设 X 还覆盖了复制和移动赋值操作符和构造函数,那么像 x = a + b 产生任何复制?为什么会产生复制?
c++ operator-overloading
1个回答
1
投票

我不知道这是否有那个例子编写者的想法,但有一些解释。考虑一下这段代码中发生了什么。

X a, b, c;
X d = a + b + c;

这里,首先, a + b 基本上被评价为 operator+(operator+(a, b), c). 注意到 operator+(a, b) 是一个 r值因此, lhs 可以,在外在应用 operator+,通过以下方式初始化 移动施工人员.

另一种实施方式 operator+ 就...而言 operator+= 如下所示。

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

请注意,你需要创建一个临时对象,因为你需要一个对象来申请 operator+= 上。有了这个解决方案,这两种应用的 operator+operator+(operator+(a, b), c) 涉及 抄写员.

现场演示。https:/godbolt.orgz5Dq7jF

当然,你可以添加第二个版本,用于 r值 如下。

friend X operator+(X&& lhs, const X& rhs) 
{    
   lhs += rhs;
   return std::move(lhs);
}

但这比原来的值传递版本需要更多的输入。


一般来说,通过值传递经常被用于想要统一lvalues和rvalues的重载的情况下;例如,寻找一下 统派运算符.

© www.soinside.com 2019 - 2024. All rights reserved.