Search code examples
c++classconstants

Why it is needed to use const A& instead of just A&?


I was wondering why it is needed to use const A& in this situation, Why can't I use just A&? according to what I read is because it specified that it won't change the object. Is there any other reason? I would like a better explanation.

Code:

#include<iostream>
#include<set>

class A{
public:
    int x;
    A(int x=0): x{x} {std::cout<<"Construct"<<std::endl;};
    A(const A& rhs) {x=rhs.x;std::cout<<"Copy"<<std::endl;}
};

bool operator < (const A& lhs,const A& rhs) {return lhs.x<rhs.x;}

int main(){
    std::set<A> Set;
    A a(10);
    Set.insert(a);
    Set.emplace(10);
    return 0;
}

Solution

  • A& is an lvalue reference, which means it can change the thing it's looking at. With

    A(A& rhs)
    

    you can call it like

    int x = 10;
    A a(x);
    

    And then any changes to rhs in the constructor will change the actual variable x. And that's fine. But when you do

    A a(10);
    

    That's a problem. Because if someone changes rhs in the constructor, that means we have to "change" the number 10, and that's not really even a meaningful thing to do. 10 += 1 is nonsense in C++, for instance.

    const A& is a guarantee that we aren't going to change the thing being pointed to, so it becomes safe to pass a temporary value like 10 to the function.

    If we knew it was always a "small" datatype like int, we might take it by value, but we don't want to take an A as argument, since some types (like vectors) can be expensive to copy, and others (like unique_ptr) are outright impossible to copy.

    Depending on your use case, you can consider using A&&, an rvalue reference. This is useful if you intend to move the value into the class you're constructing, rather than make a copy of it. You can read more about move semantics on this question, but if you're just starting out in C++, it's probably best to stay away from rvalue references. It is good to be aware that they exist, though.