简体   繁体   English

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

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

Could somebody explain what the difference is in this example of operator overloading, Average& operator+=(int num) where you return a reference to Average versus not returning a reference to Average ie Average operator+=(int num) . 有人可以解释一下这个算符重载示例Average& operator+=(int num)的区别是什么,在该示例中,您返回对Average的引用而不是不返回对Average的引用,即Average operator+=(int num)

Does returning a reference mean return a reference to the object being assigned to (not a copy) which is *this . 返回引用是否意味着返回对分配给*this的对象的引用(不是副本)。 So in this case return a reference to the object avg . 因此,在这种情况下,返回对对象avg的引用。

How/why does the non reference version work? 非参考版本如何/为什么起作用? Where is the result being copied? 结果在哪里复制?

#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;
}

When overriding operators in C++, one can provide them in multiple forms. 在C ++中重写运算符时,可以以多种形式提供它们。 You can define assignment operators which do not return a reference to the modified object, and they would work as expected. 您可以定义赋值运算符,这些赋值运算符不返回对已修改对象的引用,它们将按预期工作。 But, we have for each operator what we call a canonical implementation : 但是,对于每个运算符,我们都有所谓的规范实现

Other than the restrictions above, the language puts no other constraints on what the overloaded operators do, or on the return type (it does not participate in overload resolution), but in general, overloaded operators are expected to behave as similar as possible to the built-in operators: operator+ is expected to add, rather than multiply its arguments, operator= is expected to assign, etc. The related operators are expected to behave similarly ( operator+ and operator+= do the same addition-like operation). 除了上述限制之外,该语言对重载运算符的操作或返回类型(返回类型(不参与重载解析))没有任何其他限制,但是通常,重载运算符的行为应尽可能与重载运算符相似。内置运算符: operator+应该加而不是乘以其参数, operator=应该赋值,等等。相关运算符的行为类似( operator+operator+=进行相同的加法运算)。 The return types are limited by the expressions in which the operator is expected to be used: for example, assignment operators return by reference to make it possible to write a = b = c = d , because the built-in operators allow that. 返回类型受到期望使用该运算符的表达式的限制:例如,赋值运算符通过引用返回,从而可以编写a = b = c = d ,因为内置运算符允许这样做。

Commonly overloaded operators have the following typical, canonical forms. 通常,重载运算符具有以下典型的规范形式。

There is a lot to read about those canonical forms, but I'd suggest to start with this really good SO answer on What are the basic rules and idioms for operator overloading? 关于这些规范形式有很多文章要阅读,但是我建议从关于操作符重载的基本规则和惯用法是什么的这个非常好的SO答案开始


How/why does the non reference version work? 非参考版本如何/为什么起作用?

Because even if the C++ Standard encourages you to use the canonical forms, it doesn't forbid you not to. 因为即使C ++标准鼓励您使用规范形式,也不会禁止您不使用规范形式。

Where is the result being copied? 结果在哪里复制?

Nowhere, the value is discarded. 该值无处被丢弃。 Implementation will probably optimize them away. 实施可能会优化它们。

Does returning a reference mean return a reference to the object being assigned to (not a copy) which is *this. 返回引用是否意味着返回对分配给该对象的引用(不是副本),即* this。 So in this case return a reference to the object avg. 因此,在这种情况下,返回对对象avg的引用。

Yes. 是。

How/why does the non reference version work? 非参考版本如何/为什么起作用? Where is the result being copied? 结果在哪里复制?

The returned value is a temporary object that is passed to std::cout << . 返回的值是一个临时对象,该对象传递给std::cout <<

It's similar to using: 它类似于使用:

int foo()
{
   return 10;
}

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

The return value of foo is a temporary object that is passed to std::cout << . foo的返回值是一个临时对象,传递给std::cout <<

You should return a reference because thats a convention most code in standard library is using, and most programmers do. 您应该返回一个引用,因为多数民众赞成在标准库中使用的是多数民众赞成的惯例。 Most programmers will expect below code: 大多数程序员会期望以下代码:

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

to print b , or in this example: 打印b ,或在此示例中:

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

will expect 100 to be printed. 预计将打印100张。

That is why you should return a reference to keep with the convention which allows to modify object which is on the left side of assignment. 这就是为什么您应该返回引用以遵守约定的原因,该约定允许修改位于分配左侧的对象。

Otherwise, if you return by value (a copy) assignment as in above examples will assign to a temporary. 否则,如果您按上述示例中的值(副本)返回,则将分配给一个临时对象。

Try to check this similar question . 尝试检查这个类似的问题

When you return reference, you are actually passing the actual object. 返回引用时,实际上是在传递实际对象。 While when you return by value, temporary object is created and then passed to caller. 当您按值返回时,将创建临时对象,然后将其传递给调用方。

So if you return without reference this assignment may work as per your code segment above. 因此,如果您返回但没有参考,则该分配可能按照上面的代码段工作。

Average aa = avg += 4;

But it will fail to compile if you try. 但是如果尝试,它将无法编译。

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

The above code will work if you return reference though, since we are passing valid scope of object. 如果您返回引用,上述代码将起作用,因为我们正在传递对象的有效范围。

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

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