简体   繁体   中英

Why do you need to use const in following operator overloading?

This is a code for adding 3 objects of class Integer

#include <iostream>
using namespace std;
class Integer
{
    int value;
    public:
    Integer(int i) 
    { 
        value = i; 
    };
    int getValue() 
    { 
        return value; 
    }
    friend Integer operator+(const Integer & a,const Integer & b)
    {
        Integer i(a.value+b.value);
        return i;
    }
};
int main()
{
    Integer a(1), b(2), c(3);
    Integer d = a + b + c; //****HERE****
    cout << d.getValue() << endl;
    return 0;
}

Can someone please explain why const is added to parameters in this case. If I remove const, during compilation I get invalid operands to binary operation error. Adding to this question: When I only add a and b without const, output is 3 without any errors. However, adding 3 a+b+c objects, I get an error. Why is that?

Let's say hypothetically we had written this function:

friend Integer operator+(Integer& a, Integer& b);

Stylistically, this isn't great because operator+ shouldn't be modifying its arguments. But let's say we don't care about that. Now, what happens when we try to do this:

Integer d = a + b + c;

This is grouped as (a+b)+c . The a+b subexpression will find our operator+() , which is a viable function because a and b are non- const lvalues of type Integer , and the result of that expression is an rvalue of type Integer .

The subsequent expression is {some rvalue Integer} + c . That expression we won't be able to find a viable function for. While c can bind to Integer& , the first argument cannot - you can't bind an rvalue to a non- const lvalue reference. So you'd have to write something like:

Integer tmp = a + b; // OK
Integer d = tmp + c; // also OK

but now we're introducing this extra name into our scope and an extra statement into our code just to get around the unviability of our function signature.

Because you're trying to bind a Temporary to a [non-const-]reference, which isn't allowed in C++.

In the code Integer d = a + b + c; , a + b is evaluated first, and creates a new temporary object which then gets evaluated against c. So the code then becomes Integer d = t<a+b> + c; . Because the first object is now a temporary, only three function signatures will accept it as a parameter: const Integer & , Integer , and Integer && . The second is not advised because it will create a copy of the object (though, sometimes that's what you want!), and the latter isn't advised because it will refuse to accept persistent objects. The first option, then, is best, because it will accept any Integer object regardless of whether it's expiring or not.

Recommended Reading: What are rvalues, lvalues, xvalues, glvalues, and prvalues? It's very verbose, and will probably require several passes before you "get" it, but it's extremely valuable knowledge for any C++ programmer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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