-4

So, let us say we have the following class:

Why must I put Class& instead of Class as return-type? If I were to have a static variable, which would count my objects, putting the return-type as Class , without &, would increase the count var even though I haven't called any constructor, default, copy, not even one. Yet, it is incremented. Can someone explain?

class Class {

public:
   int x;
   static int count;
   
   Class& operator=(const Class& c) {
      this->x = c.x;

}

    


};

I have looked for an explanation on the internet, but no good answer has been found. I hope someone on StackOverflow could answer my inquiry.

  • *"Why must I put Class& instead of Class as return-type?"* It is an option. You can also use `Class` as return type. Nobody is stopping you. See [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading). Also [Why we use reference return in assignment operator overloading](https://stackoverflow.com/questions/21485366/why-we-use-reference-return-in-assignment-operator-overloading-and-not-at-plus-m) – Jason Nov 05 '22 at 14:48
  • yes, I'm fully aware of that, but Class simply would call a constructor, and it would increase my count variable, given the constructor would have something like count++. Why is that? – decrepitude Nov 05 '22 at 14:49
  • [Why must the copy assignment operator return a reference/const reference?](https://stackoverflow.com/questions/3105798/why-must-the-copy-assignment-operator-return-a-reference-const-reference) – Jason Nov 05 '22 at 14:53
  • A new object being created by the assignment operator is unexpected as would be not being able to access the lhs of the assignment e.g. in `Class obj; Class obj2; auto& lhs = (obj = obj2);`. If the operator is implemented as `Class operator=(Class const& other) { ... return *this; }` the compiler must create an additional object that's a copy of `this` created via copy constructor. – fabian Nov 05 '22 at 14:53
  • 1
    When new object are created a constructor is called. Even if the returned object isn't used by the way. – QuentinUK Nov 05 '22 at 14:54

1 Answers1

1

That's because of a feature of C++ called implicit class type conversion. Without the &, your assignment operator has a return type of Class. That means it can be used as a conversion function, to implicitly convert from Class to Class. And since it doesn't actually return anything, it effectively converts a Class to a default-constructed Class... which increments the count. By making the return type Class&, you're disabling that implicit conversion, and requiring an lvalue to be returned - which your operator= does, by returning *this. So now it just acts as a normal assignment operator, without unexpected side-effects.

HKTE
  • 167
  • 5
  • *"since it doesn't actually return anything, it effectively converts a Class to a default-constructed Class"* Not necessarily, if you leave a function with a return type other than `void` by reaching the end of the function, you've got undefined behaviour. – fabian Nov 05 '22 at 14:57
  • You are correct, returning from a function with a non-void return type without an actual return value results in undefined behavior. The compiler is allowed to assume that a non-void function will always return a valid value of the correct type, and may optimize based on that assumption. This can lead to very strange bugs if the assumption is violated by not having a return statement (or returning void from a non-void function). It's best to always have a return statement for every code path in a non-void function, and to return a value of the correct type. – HKTE Nov 05 '22 at 15:00