Yes! We indeed have a copy here since we are passing parameters
by value. Remember, that when we pass parameters by value, the arguments
are evaluated and copied into the function parameters.
We thus inded have a copy of r1 which will be copied into "r", a parameter
of the "f" function. During the call to f of r1,
the copy constructor of the "Rectangle" class is called.
The copy constructor is called because of passing parameters by value here;
thus resulting in a copy. Obviously, if we pass the parameters by reference, there is
no copy at all; the copy constructor is thus not called.
The goal of the copy constructor is to initialize an instance with a copy
of another instance of the same class
Its prototype is thus fixed. Since it is a constructor,
its name is none other than the class name. And since it initializes
with a copy of another instance of the same, it will only
receive one single parameter here. This parameter is another instance of the same class.
We will pass this other instance by constant reference in other to avoid
passing parameters by value which would create another copy.
In this case, we would enter an infinite loop! making a copy of a copy of a copy...
Therefore, we use the passage by reference. Also, the copy constructor
does not modify the received instance but only modifies the instance
it is currently initializing. Thus, it does not modified the received
instance : this is a constant reference.
For example, in our rectangle case, we would have here
a constructor called "Rectangle" for the "Rectangle" class.
It would receive another instance of the same "Rectangle" class, passed by
constant reference. Of course, it would use the initialization section
starting with a colon.
Here initializing the height of the instance it is creating
with the value of the height of the other instance received
as parameter. And similarly, initializing the width of the
instance it is creating with the copy of the width of the other instance
received as parameter.
let us go back to the previous example. We have an r2 instance
created with a copy of the r1 instance. We indeed have a call to the copy
constructor. In this case, r1 is the received parameter
and r2 the initialized instance. Here, we thus have "r2.hauteur"
receiving "r1.hauteur" and "r2.largeur" receiving "r1.largeur".
By the way, often it is not necessary to write explicitly the
copy constructor. Indeed, the C++ compiler provied us with
a default one.
There is always a copy constructor furnished by default. We call it
copy constructor is build
This copy constructor carries out a so-called shallow copy.
This means that it will copy the parameter attributes of the other
received instance one after the other in order to process the current initialization.