Reputation: 47
I am a beginner in programming and I am learning about copy constructors. From different sources I can see that copy constructors are useful if I want to "deep copy" a class object so the new object's pointer members will point to new memory locations.
My question is, what is the advantage of defining the copy constructor as I do in class CopyCat in my example, if I get the same result with an empty copy constructor (as in class EmptyCat)?
My second question is, why do class Cat and class EmptyCat work differently? The only difference between them is that I define an empty copy constructor in EmptyCat. But as I run the program I can see that in EmptyCat after the copying the pointer member points to a new location while in class Cat it works as a shallow copy.
#include "iostream"
class Cat
{
public:
void GetMem() { std::cout << itsAge << "\n"; }
private:
int * itsAge = new int;
};
class EmptyCat
{
public:
EmptyCat() {}
~EmptyCat() {}
EmptyCat(EmptyCat&obj) {}
void GetMem() { std::cout << itsAge << "\n"; }
private:
int * itsAge = new int;
};
class CopyCat
{
public:
CopyCat() {}
~CopyCat() {}
CopyCat(CopyCat&obj);
int GetAge() { return *itsAge; }
void GetMem() { std::cout << itsAge << "\n"; }
private:
int * itsAge = new int;
};
CopyCat::CopyCat(CopyCat & obj)
{
itsAge = new int;
*itsAge = obj.GetAge();
}
int main()
{
Cat Garfield;
Cat Kitty(Garfield);
std::cout << "Memory addresses for the objects' <itsAge> member:" << std::endl;
std::cout << "Garfield and Kitty (Class Cat):" << std::endl;
Garfield.GetMem();
Kitty.GetMem();
EmptyCat Meow;
EmptyCat Purr(Meow);
std::cout << std::endl << "Meow and Purr (Class EmptyCat):" << std::endl;
Meow.GetMem();
Purr.GetMem();
CopyCat Fluffy;
CopyCat Felix(Fluffy);
std::cout << std::endl << "Fluffy and Felix (Class CopyCat):" << std::endl;
Fluffy.GetMem();
Felix.GetMem();
system("pause");
return 0;
}
If I run the program I get this:
Memory addresses for the objects' <itsAge> member:
Garfield and Kitty (Class Cat):
00BBDA60
00BBDA60
Meow and Purr (Class EmptyCat):
00BB46A0
00BB8280
Fluffy and Felix (Class CopyCat):
00BB82B0
00BBE8A0
Press any key to continue . . .
Upvotes: 2
Views: 4698
Reputation: 92321
My question is, what is the advantage of defining the copy constructor as I do in class CopyCat in my example, if I get the same result with an empty copy constructor (as in class EmptyCat)?
You don't get the same result. CopyCat
allocates new memory and copies the value from the old class. The EmptyCat
just allocates new memory, but does not copy the value.
My second question is, why do class Cat and class EmptyCat work differently? The only difference between them is that I define an empty copy constructor in EmptyCat. But as I run the program I can see that in EmptyCat after the copying the pointer member points to a new location while in class Cat it works as a shallow copy.
In Cat
you haven't declared a copy constructor, so the compiler will generate one when needed. The default copy constructor does a member-wise copy from the original. In your case, this will copy the pointer (so that it stores the same address as the original).
In the EmptyCat
you have a user defined copy constructor. But as that one doesn't handle the pointer member, its default value will be used.
int * itsAge = new int;
This is what allocates a new int
and gets you a different pointer value.
Upvotes: 1
Reputation: 6404
Deep copying and shallow copying is rather a C concept, where you have only structures and raw pointers. A pointer can be owned, in which case the copy must be deep, or it can be shared, in which case the copy is shallow (and you have to be careful about freeing it if it's allocated with malloc).
In C++, new is now effectively deprecated. We have unique pointers, which are "owning pointers" and "shared pointers". However pointers are relatively rare. Array members of classes are std::vectors, string members are std::strings. And copies are automatically deep, (You use a reference if you want a shallow copy).
Pointers are held back for relatively unusual situations, like trees and graphs.
Upvotes: 2
Reputation: 5409
You are not getting the same behavior with and without an empty copy constructor. EmptyCat(EmptyCat& obj) { }
does absolutely nothing.
CopyCat(CopyCat& obj) {
itsAge = new int;
*itsAge = obj.GetAge();
}
dynamically allocates a new int
and assigns to it a value from the obj
.
Upvotes: 0