使用运算符重载形式

Using of Operator Overloading form

我想知道在 c++ 中关于以下运算符重载形式的问题:

ClassName & operator+(ClassName &other)
ClassName operator+(ClassName &other)
Classname operator+(const ClassName &other)
Classname operator+(const Classname other)
Classname operator+(Classname other)

用法有什么区别??

第一个 return 是一个引用,并接受一个引用 - 这意味着理论上您可以更改两个参数,并且您 return 是一个引用,它也可以更改。这通常不是您想要做的(2 + 3 不会 return 5 可以重新分配给 17)。

第二个相同,但没有参考 returned。

第三个有常量引用 - 无法修改的引用。这通常是您想要做的,因为您可以快速获取元素(您可以获取 the 元素),但您无法更改它(无论是否偶然)。

第四个与第三个类似,但您复制了一个参数,并出于某种原因将其设为常量。这没什么意义。

最后一个只拿了一份。

其中一些之间没有太大区别 - 如果您考虑 operator+ 必须做什么,其中一些就没有什么意义;它们的不同之处主要在于你如何获得论点 - 大多数时候,你想要快速获得它,所以 const ClassName& other 可能是你最好的选择。

仅供参考:none中引用的运算符是正常的 实际上超载了!通常超载的更像是 this(假设它与 ClassName 在同一个命名空间中):

ClassName operator+ (ClassName const& op1, ClassName const& op2) {
    ClassName rc(op1);
    rc += op2;
    return rc;
}

此运算符的实现方式有一些变化。在 特别是第一个参数可以按值传递以避免复制 在实施中:在某些情况下可以省略副本。这种使用命名变量并按名称 return 对其进行特定实现的目的是启用复制省略(正如@juanchopanza 指出的那样,return ClassName(op1) += op2; 不允许省略 return 的副本值)。

关于你的实际问题,区分是很重要的 引用和值之间:

  • 当使用像 ClassName 这样的值时,对象被传递给 function 或 returned from a function 是一个副本。当 class 有问题的是微不足道的,那没关系,但是如果 class 更多 复杂并为其成员分配内存可能有一些 创建实际副本的成本。另一方面,在语义上它是 通常需要使用副本。例如,加法的结果 通常是一个不同的对象,因此需要一个副本。

    为了减少一些成本,编译器会尝试 尽可能避免复制。例如,当 returning a 局部变量副本在许多情况下被省略或者对象是, 至少,移动了(假设使用 C++11 或更高版本并且 class 有 移动构造函数)。

  • 当使用像ClassName&ClassName const&这样的引用时, 实体实际上只是一个对象的名称。没有复制 但是一个对象需要存在于某个地方。 const 的存在与 缺少 const 仅表示是所有方法还是仅 const 可以调用方法或是否可以传递引用 需要其他参考的地方:非 const 参考可以 被转换为 const 引用但不是反之亦然。

    为参数目的,关键区别const 引用和非const引用是临时对象 无法绑定到非 const 引用,而它们 可以 绑定到 const 参考文献。

排序后,这里是 运行-through 的不同声明 operator+():

  • ClassName & operator+(ClassName &other)

    此声明采用非const 引用作为参数和returns 非 const 参考。对于这个论点,这意味着它不能 是临时的,但需要有一个名字。对于 return 意味着 returned 对象需要保持活动状态。通常情况下 添加创建一个新对象并尝试使对象保持活动状态 肯定是行不通的。如果ClassName复制真的很贵 您可能不想提供 operator+() 而只是 一个 operatr+=() 在语义上产生与 operator+() 但就地这样做。

  • ClassName operator+(ClassName &other)

    这个声明的主要约束是参数是 非 const 引用,即参数不能是临时的 对象,但必须是左值,即某种以某种方式存在的东西 命名。但是,参数不会被复制。

  • ClassName operator+(const ClassName &other)

    此声明适用于临时文件,并且是两种可能的声明之一 成员 operator+() 会是什么样子的候选人。争论 仍然没有被复制但是因为它是[逻辑上]不可变的临时 对象可以用作参数。

  • ClassName operator+(const ClassName other)

    这将复制参数。为声明之目的 const 将毫无意义,它实际上可以不同 同一个函数的不同声明。当定义 使用这个声明意味着参数被复制,即 operator+() 有一个本地版本,但它实际上不能改变这个 复制。很可能需要创建另一个副本来生成 结果。相应地,我认为用 const 定义一个函数 value 参数完全没有意义:如果你想要一个常量,使用 const ClassName&ClassName const&(它们是相同的;我做 更喜欢后一种表示法,因为它会导致一致的放置)。

  • ClassName operator+(ClassName other)

    和前面的声明一样,这个声明复制了参数,但是 参数是可变的。假设操作是可交换的,你可以 轻松地改变 other 以产生 return 值。但是请注意, 复制 other 不会被省略(不允许编译器 省略复制函数参数)但它可以移动。假设 ClassName 要么复制便宜,要么 other 被用作基础 对于结果,这是另一个可能的候选者 已定义。