In Deitel C++ book ("C++11 for Programmers", p.286) , there is an example of:
class Date { ... }
class Employee {
public:
Employee(const string &, const string &, const Date &, const Date &);
private:
string firstName;
string lastName;
const Date birthDate;
const Date hireDate;
}
Employee::Employee( const string &first, const string &last,
const Date &dateOfBirth, const Data &dateOfHire)
: firstName( first),
lastName( last),
birthDate(dateOfBirth),
hireDate(dateOfHire) { };
The book says the member initializer such as birthDate(dateOfBirth)
invoked Date
class's copy constructor. I am confused as to why copy constructor? I thought the whole point of "pass by reference" is to avoid the object copy?
If I do:
Date birth(7,24, 1959);
Date hire(2,12, 1988);
Employer staff("bob", "blue", birth, hire);
How many Date objects does the system have now, 2 or 4? (Two created at the start, two are created by copy constructor)
When an object (or built-in type) is passed by reference to a function, the underlying object is not copied. The function is given the memory address of the object itself. This saves both memory and CPU cycles as no new memory is allocated and no (expensive) copy constructors are being called.
Passing by references ensures an actual object is passed to the copy constructor, whilst a pointer can have NULL value, and make the constructor fail.
Passing by value (rather than by reference) means a copy needs to be made. So passing by value into your copy constructor means you need to make a copy before the copy constructor is invoked, but to make a copy you first need to call the copy constructor.
The point of "pass by reference" is to not make a copy as soon as Employee constructor is called, but only when you choose to initialize one of Employee's member with the Date passed.
It is not the passing-mode that involves a copy.
It is the initialization of the members that invove a copy (obviously? the parameters don't live in the class, and the class members need to get the same value: copy)
Let's examine
Employee::Employee( const string &first, const string &last,
const Date &dateOfBirth, const Data &dateOfHire)
: firstName( first),
lastName( last),
birthDate(dateOfBirth),
hireDate(dateOfHire) { };
//
int main()
{
const std::string fname = "test";
Employee e(fname, /* ..... */);
}
Employee::Employee
, passing fname
by const&
(no copy).std::string(const std::string&)
, again passing the parameter on by const&
(still no copy).std::string
copy constructor now takes all necessary steps to copy the the value of it's parameter into the object itself. This is the copy
It makes sense that when you construct a new std::string
(in this case as a member of Employee), it results in a ... new std::string
. Thinking of it this way makes it very easy to grasp, I think.
Your original object birth
is indeed passed by reference to the Employee
copy constructor, so no copy is made at that stage. However, when the Employee
copy is being constructred, the member Employee::birthDate
object is initialized by using its own copy constructor, to which the outer birth
object is passed by reference, but that copy constructor will of course make a copy of the birth
object, which becomes the Employee::birthDate
member object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With