繁体   English   中英

c ++运算符+ =重载返回引用

[英]c++ operator += overloading return reference to

有人可以解释一下这个算符重载示例Average& operator+=(int num)的区别是什么,在该示例中,您返回对Average的引用而不是不返回对Average的引用,即Average operator+=(int num)

返回引用是否意味着返回对分配给*this的对象的引用(不是副本)。 因此,在这种情况下,返回对对象avg的引用。

非参考版本如何/为什么起作用? 结果在哪里复制?

#include <iostream>
#include <cstdint> // for fixed width integers

class Average
{
private:
    int32_t m_total = 0; // the sum of all numbers we've seen so far
    int8_t m_numbers = 0; // the count of numbers we've seen so far

public:
    Average()
    {
    }

    friend std::ostream& operator<<(std::ostream &out, const Average &average)
    {
        // Our average is the sum of the numbers we've seen divided by the count of the numbers we've seen
        // We need to remember to do a floating point division here, not an integer division
        out << static_cast<double>(average.m_total) / average.m_numbers;

        return out;
    }

    // Because operator+= modifies its left operand, we'll write it as a member
    Average& operator+=(int num)
    {
        // Increment our total by the new number
        m_total += num;
        // And increase the count by 1
        ++m_numbers;

        // return *this in case someone wants to chain +='s together
        return *this;
    }
};

int main()
{
    Average avg;

    avg += 4;
    std::cout << avg << '\n';


    return 0;
}

在C ++中重写运算符时,可以以多种形式提供它们。 您可以定义赋值运算符,这些赋值运算符不返回对已修改对象的引用,它们将按预期工作。 但是,对于每个运算符,我们都有所谓的规范实现

除了上述限制之外,该语言对重载运算符的操作或返回类型(返回类型(不参与重载解析))没有任何其他限制,但是通常,重载运算符的行为应尽可能与重载运算符相似。内置运算符: operator+应该加而不是乘以其参数, operator=应该赋值,等等。相关运算符的行为类似( operator+operator+=进行相同的加法运算)。 返回类型受到期望使用该运算符的表达式的限制:例如,赋值运算符通过引用返回,从而可以编写a = b = c = d ,因为内置运算符允许这样做。

通常,重载运算符具有以下典型的规范形式。

关于这些规范形式有很多文章要阅读,但是我建议从关于操作符重载的基本规则和惯用法是什么的这个非常好的SO答案开始


非参考版本如何/为什么起作用?

因为即使C ++标准鼓励您使用规范形式,也不会禁止您不使用规范形式。

结果在哪里复制?

该值无处被丢弃。 实施可能会优化它们。

返回引用是否意味着返回对分配给该对象的引用(不是副本),即* this。 因此,在这种情况下,返回对对象avg的引用。

是。

非参考版本如何/为什么起作用? 结果在哪里复制?

返回的值是一个临时对象,该对象传递给std::cout <<

它类似于使用:

int foo()
{
   return 10;
}

std::cout << foo() << std::endl;

foo的返回值是一个临时对象,传递给std::cout <<

您应该返回一个引用,因为多数民众赞成在标准库中使用的是多数民众赞成的惯例。 大多数程序员会期望以下代码:

std::string s;
(s += "a") = "b";
std::cout << s << std::endl;

打印b ,或在此示例中:

int n = 10;
(n += 20) = 100;
std::cout << n << std::endl;

预计将打印100张。

这就是为什么您应该返回引用以遵守约定的原因,该约定允许修改位于分配左侧的对象。

否则,如果您按上述示例中的值(副本)返回,则将分配给一个临时对象。

尝试检查这个类似的问题

返回引用时,实际上是在传递实际对象。 当您按值返回时,将创建临时对象,然后将其传递给调用方。

因此,如果您返回但没有参考,则该分配可能按照上面的代码段工作。

Average aa = avg += 4;

但是如果尝试,它将无法编译。

Average *ptr = &(avg += 4);

如果您返回引用,上述代码将起作用,因为我们正在传递对象的有效范围。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM