Copy constructor and dynamic memory - c++

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 . . .

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.

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.

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.

Related

how to disable move construct base class from derived class?

In the following code, I want to disable the move construction of base class Vector from derived class VectorMap, and call the copy constructor.
#include <iostream>
#include<algorithm>
struct Vector{
int* _ptr=nullptr;
int _size=0;
Vector(int n){
_ptr = new int[n];
_size = n;
std::cout<< " Construct "<<this<<std::endl;
}
Vector(void) { std::cout <<" Construct " << this << std::endl; }
virtual ~Vector(void) {
if (_ptr != nullptr) {
std::cout << "Deconstruct " << this << " -> delete " << _ptr << std::endl;
delete _ptr;
return;
}
std::cout << "Deconstruct " << this << std::endl;
}
Vector(Vector&& v2) noexcept {
int* p2=v2._ptr; int s2=v2._size;
v2._ptr=_ptr;
v2._size=_size;
_ptr=p2; _size=s2;
std::cout << "Move construct " << this << std::endl;
}
Vector(const Vector& v3){
_ptr=new int[v3._size];
_size=v3._size;
memcpy(_ptr,v3._ptr,sizeof(int) * _size);
}
};
struct VectorMap
: public Vector {
VectorMap(int* p,int size){
_ptr=p;
_size=size;
}
~VectorMap(void) override {
_ptr=nullptr; _size=0;
}
};
int main(void) {
Vector v1(10);
Vector v2=VectorMap(v1._ptr,5); // v1._ptr will be deleted twice
return sizeof(v2);
}
As you can see, if move constructor is called in the line Vector v2=VectorMap(v1._ptr,5);, the data pointer in v1 will be deleted twice, one is by v2, and another is by v1. Since they share the same pointer. Is there any way to modify VectorMap to call copy constructor rather than move constructor in such case?
The primary problem is muddy ownership semantics.
Vector creates a resource (dynamic array), and is apparently intended to have unique ownership over it.
VectorMap on the other hand takes a pointer in its constructor, and gives it to its base Vector that takes ownership. But right before destruction, VectorMap rescinds the ownership by setting the base Vector pointer to null. So, VectorMap sort of pretends to own the resource until it's time for the responsibility of the ownership at which point it backs down.
This inheritance also causes other problem situations. Consider for example making a copy of VectorMap. Look at what the copy constructor of the base does. It allocates memory for the copy. But the desturctor of the VectorMap copy sets the pointer to null, so in this case the pointer is deleted zero times. It leaks memory.
As an analogy, disabling slicing would be a bandage for the wound, but what you really should do is to not stick your hand inside a running blender. If VectorMap is supposed to not have ownership, then it shouldn't inherit a base that takes ownership. It's unclear to me what the point of VectorMap class even is.
Furthermore, a class that has unique ownership of a resource such as Vector really should encapsulate that bare pointer with private access specifier. Sure, such classes sometimes still provide a way to copy or throw away that value (like std::vector::data and std::unique_ptr::release), but it's important that only happens through a specific function to reduce chance of accidental violation of ownership semantics.
Another serious bug:
_ptr=new int[v3._size];
// ...
delete _ptr;
You must not delete a pointer to a dynamic array. You must use delete[]. Using delete results in undefined behaviour.
Another bug: You forgot to include the header that declares memcpy. Also, I would recommend using std::copy instead.

references and pointers in the context of C++ classes

I would like to ask a question about references and pointers in C++.
I am a beginner in C++ so I apologise for if the answer is trivial.
I have written the following code as part of a tutorial.
#include <iostream>
using namespace std;
class Deep {
private:
int *data;
public:
void set_data_value(int d) {*data = d;}
int get_data_value () {return *data;}
// Constructor
Deep (int d);
// Copy constructor
Deep (const Deep &source);
// Destructor
~Deep();
};
Deep::Deep(int d) {
data = new int;
*data = d;
}
Deep::Deep (const Deep &source)
: Deep (*source.data){ // main body of the constructor (delegation comes before the body)
cout << "Copy Constructor - deep copy" << endl;
}
Deep::~Deep() {
delete data;
cout << "Destructor deleting data" << endl;
}
void display_deep (Deep s) {
cout << s.get_data_value() << endl;
}
int main () {
Deep obj1 {100};
display_deep (obj1);
Deep obj2{obj1};
obj2.set_data_value(1000);
cout << endl;
return 0;
}
This code works. I will explain what I have done:
I defined a class named Deep to practice a deep copy. The pointer named data is private and I've included (and later defined) the function prototypes set_data_value and get_data_value.
set_data_value takes in an integer d, dereferences data and assigns the value d to it.
get_data_value simply returns the dereferenced value of data.
In the public domain also there is a constructor that accepts one integer d, a copy constructor which keeps the object constant and takes in a reference &source alongside a destructor.
Inside the copy constructor, I use a delegation constructor to improve the flow of the code.
However, if we observe the copy constructor
Deep::Deep (const Deep &source)
: Deep (*source.data){ // main body of the constructor (delegation comes before the body)
cout << "Copy Constructor - deep copy" << endl;
}
we know that this is run upon the pass-by-value nature of void display_deep (Deep s), so source is a reference to our s passed in. We then point to source and somehow obtain the value of data, which is then passed to the constructor.
How does this work? Does *source.data work as I described or does the compiler take a different route?
We then point to source and
There is no pointing to anything. In this line:
: Deep (*source.data)
You are just accessing the data inside source. Then you are dereferencing it. Just like you dereference *data to get the value inside it.

How to prove that Copy Constructor is mandatory

I Have just created a class with an integer variable and a pointer variable. After creating its object , I passed it to a function. Even after returning the function the program is not throwing the exception
#include"iostream"
using namespace std;
class A
{
public :
int i;
char *c;
void show();
};
void func(A obj);
int main()
{
A a;
a.i = 10;
a.c = "string";
cout << " Before Fun " << endl;
a.show();
cout << " Going To Call func " << endl;
func(a);
cout << " After func " << endl;
a.show();
return 0;
}
void A::show()
{
cout << " The valuses in Object are " << i << '\t' << c << endl;
}
void func(A aa)
{
cout << " The valuses in Object are " << aa.i << '\t' << aa.c << endl;
}
In The Func I am passing the object a (from main) and it would get copied in aa (stack of func). so after returning from the func if i call show ( the pointer c would be null of a), It would give me exception
But it is not happening . please help me to prove the requirement of copy constructor
Hide the copy constructor. That will cause a compilation error everywhere it is called implicitly.
class A
{
public :
int i;
char *c;
private:
A(const A& _other);
};
If no copy constructor is declared for an object, one is implicitly defined. This copy constructor copies each element of the object.
In your example, the call to func(a) will call this copy constructor, and so aa will be a copy of a (aa.i will be 10 and aa.c will point to the first element of "string").
If you are using C++11 you can do the following to remove the copy constructor
class A
{
public :
int i;
char *c;
void operator=(const A& _other) = delete;
A(const A& _other) = delete;
};
or even better:
class A : public NonCopyable // perhaps std:: or if you prefer boost, boost::
{
public :
int i;
char *c;
};
http://en.wikipedia.org/wiki/C++11#Explicitly_defaulted_and_deleted_special_member_functions
When you make a class, a null constructor and copy constructor exist implicitly.
So that is why it does not throw an exception.
However, if you define ANY constructor, you will then need to define others otherwise the rest of the constructors will be overwritten.
For example, you define a null constructor only. Then it will throw an exception. Because the implicitly defined copy constructor will be overridden.
This is one way of proving the need of a copy constructor.
An implicit copy constructor does exist if you do not define one explicitly. It is called in your func() function. A object is copied and assigned a value for its member i.
Result will be: that you do get with show() the value for i that you had before when calling func. This is with no surprise because you are not doing any assignment to members of A inside A.
Implicit copy constructor by the compiler provide member-wise copy. This is what you may need in most cases.
When is default constructor not sufficient ? you have pointer like members, and need a deep-copy of it. You don't want to copy the pointer (what copy constructor would do), but rather to have the object pointed to copied. But why do you need deep copy ? You don't want to copy the pointer (which is owned by any instance of the class), and end up calling twice destructor on the same pointer. From the second call to delete on this pointer, heap corruption ensues. You may also need copy constructor made explicit for shared_pointers.
Note that, for performance reasons, it is best pass object by const reference than by value.
In your case the copy constructor provided by compiler is present.
Modify your code and write a copy constructor as:
//Default and copy constructor
A()
{
i = 0;
c = NULL;
}
A(const A& _other)
{
cout<<"In copy cons"<<endl;
}
When you will modify the code as per above when func gets called then your own copy constructor gets called in this case you will get the junk values(can not predict)
And if you modify your copy constructor code as
A(const A& _other)
{
cout<<"In copy cons"<<endl;
i = _other.i;
c = new char [(strlen(_other.c) +1)];
strcpy(c,_other.c);
}
Now you can see the differnce in both outputs and the use of Copy constructor how and where it's used.

Why is the copy constructor of the string used?

I have the following code:
class TestClass
{
public:
TestClass(){};
std::string GetTestString()
{
return (mTestString);
}
void SetTestString(const std::string& rTestString)
{
mTestString = rTestString;
}
private:
std::string mTestString;
};
TestClass* pGlobalVar;
void SomeFunction(TestClass MyClass)
{
pGlobalVar->SetTestString("cba");
std::cout << "Changed string: " << pGlobalVar->GetTestString() << std::endl;
std::cout << "Copied string: " << MyClass.GetTestString() << std::endl;
}
int main()
{
pGlobalVar = new TestClass();
pGlobalVar->SetTestString("abc");
std::cout << "Original string: " << pGlobalVar->GetTestString() << std::endl;
SomeFunction(*pGlobalVar);
delete (pGlobalVar);
}
This outputs the following:
Original string: abc
Changed string: cba
Copied string: abc
As I did not define a copy constructor for my class, I would expect that a flat copy would be made, including the pointer in the std::string. Apparently though the std::string copy constructor is used, since a change to the original string did not change the copy.
Can anyone explain to me why it did not make flat copy?
I'm using Linux with GCC 4.4.6.
As I did not define a copy constructor for my class, I would expect that a flat copy would be made
Since you didn’t define a copy constructor, C++ did for you.
The auto-generated copy constructor calls the constructor for all its member variables (if they have one).
Analogously, auto-generated constructors call all their members’ constructors, and destructors call all their members’ destructors.
As I did not define a copy constructor for my class, I would expect that a flat copy would be made, including the pointer in the std::string.
No, the implicitly generated copy-constructor will copy each data member (and base subobject) using its copy constructor if it has one.
Can anyone explain to me why it did not make flat copy?
Because that would be horribly broken. A class defines a copy constructor because it has to be copied in a certain way; in the case of std::string, it has to create a new buffer. If the new string simply held a copy of the other's pointer, then both would think they owned the same buffer, and both would try to deallocate it when they were destroyed.

C++ Class Copy (pointer copy)

It is my understanding that when you make a copy of a class that defines a pointer variable, the pointer is copied, but the data that the pointer is pointing to is not.
My question is: Is one to assume that the "pointer copy" in this case is simply instantiating a new pointer (dynamic memory allocation) of the same type? Eg., the new pointer is simply a new allocation containing an arbitrary memory address and one should take care to point that new pointer to the appropriate memory address?
I presume there is a quite simple answer to this question, and I apologize for its trivial nature, but I am trying to understand pointers at a deeper level and this came up upon my researching pointers on the internet.
Regards,
Chad
The pointer will be simply copied as a value - so both classes will point to the same original memory, no new allocation takes place. Shallow copy - this is what the language does by default.
If you need to allocate new memory and make a copy of the data you have to do that yourself in the copy constructor. Deep copy - you have to do this yourself
edit: This is one of the advantages of C++, you are free to decide how copying works. It might be that a copy of the object which only does read access to the memory can avoid the cost of copying the memory. You can also implement classes which only make a copy of the original data if the new object needs to do a write.
First off, the pointer in your class is static, (i.e. the compiler knows that there is a pointer in this class and what size it is, so no dynamic memory allocation is needed when the class is instantiated).
If you copy the class (and have not special copy constructor defined) then the pointer in the new class will point to the same place in memory as the pointer in the old class. To clarify:
#include <iostream>
class A {
public:
int *p;
};
int main() {
A a,b;
a.p = new int(10);
b = a;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10
*(b.p) = 3;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 3
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3
return 0;
}
Now if you want to allocate new memory when copying, you need to write a copy constructor and a copy assignment constructor:
#include <iostream>
class A {
public:
int *p;
A() : p(0) {}
A(const A& other) { // copy constructor
p = new int(*other.p);
}
A& operator=(const A& other) { // copy assignment constructor
// protect against self assignment
if (this != &other) {
if (p != 0) {
*p = *other.p;
} else { // p is null - no memory allocated yet
p = new int(*other.p);
}
}
return *this;
}
~A() { // destructor
delete p;
}
};
int main() {
A a,b;
a.p = new int(10);
b = a;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10
*(b.p) = 3;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3
return 0;
}
When you do this you should also write a destructor (see Rule of three ), because the memory that is being allocated in the copy / copy assignment constructors needs to be de-allocated if the class is destroyed:
Pointers don't instantiate dynamic memory allocation. Pointers and allocations are entirely different things.
If you copy a pointer that points to dynamically allocated memory, you have two pointers pointing at the same allocated memory. Since you've copied it, it already points to the memory block. Specifically, if using the compiler-generated copy constructor, the new pointer will point to the exact same thing as the old pointer. You don't need to do anything with it if that's OK.
You do have the problem of when to free the memory. Freeing it twice will typically cause heap corruption, which is nasty. Not freeing it will cause a memory leak, which may be acceptable in some circumstances. Freeing it before the other pointer is through with it will also cause problems. For this reason, people who have multiple pointers to the same memory often go to the Boost project and use their shared_ptr template (which will be in the upcoming new Standard, and is present in most up-to-date systems).
If you want each pointer to point to separate chunks of memory, you have to set that up by writing your own copy constructor, and allocating a new chunk and copying necessary data in it. (You also need to write your own assignment operator, for the exact same reasons, and your own destructor so you can free the memory. There's a rule of thumb, called the Rule of Three, that says if you need to write your own copy constructor, assignment operator, or destructor, you probably need to write all of them.)
The copied pointer will point to the exact same address. There's no new allocation.
Yes, pointers simply contain memory addresses, if you want to make a deeper copy you need to code that yourself, in the copy constructor.
If you're always referencing the same kind of data via a pointer from the same class, and need to copy the data along with the objects, you could also consider making it just a plain member, not a pointer.