0

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;
}
parse5214
  • 27
  • 1
  • 8
  • do you mean in the constructor? – pm100 Mar 23 '22 at 02:36
  • @pm100 yes, in the constructor. – parse5214 Mar 23 '22 at 02:47
  • 1
    If creating a copy of an object (e.g. defining and initialising `b` as a copy of `a`, via `A b(a);`) one often does not expect the logical state of `a` (the object being copied) to change. Qualifying the argument of the copy constructor as `const` communicates that is, indeed, the case. Among other things, this allows creating a temporary (an unnamed object within an expression, and copying the temporary). If it does make sense for the state of `a` to change, the `const` can be omitted - among other things, that does prevent copying of a temporary. – Peter Mar 23 '22 at 02:55

1 Answers1

3

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.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116