I have recently discovered that when I have pointers within a class, I need to specify a Copy constructor.
To learn that, I have made the following simple code. It compiles, but gives me runtime error when performing the copy constructor.
I am trying to copy just the value from the pointer of the copied object, but avoiding assigning the same address.
So, what's wrong here?
class TRY{
public:
TRY();
~TRY();
TRY(TRY const &);
int *pointer;
void setPointer(int);
};
void TRY::setPointer(int a){
*pointer = a;
return;
}
TRY::TRY(){}
TRY::~TRY(){}
TRY::TRY(TRY const & copyTRY){
int a = *copyTRY.pointer;
*pointer = a;
}
int main(){
TRY a;
a.setPointer(5);
TRY b = a;
b.setPointer(8);
cout << "Address of object a = " << &a << endl;
cout << "Address of object b = " << &b << endl;
cout << "Address of a.pointer = " << a.pointer << endl;
cout << "Address of b.pointer = " << b.pointer << endl;
cout << "Value in a.pointer = " << *a.pointer << endl;
cout << "Value in b.pointer = " << *b.pointer << endl;
return 0;
}
I'll be using this concept for other classes with lots of pointers in it, where I need to copy all values from on object to the other. Copying is initially necessary for this code, so I would like to keep the copying possibility (I won't be hiding the copy constructor as private).
Besides, the real class I need to implement has like 10 pointers, and it might be changing with time. Isn't there a somewhat smarter way to have a deep copy constructor in C++?...
For Class attributes that are objects themselves, their copy constructors will be called. For a Pointer Data member, the pointer will be copied, NOT what it is pointing to. This is called a Shallow Copy, as opposed to a Deep Copy.
Explanation: Whenever the compiler creates a temporary object, copy constructor is used to copy the values from existing object to the temporary object.
Copying a pointer does not copy the corresponding object, leading to surprises if two pointers inadvertently points to the same object. Destroying a pointer does not destroy its object, leading to memory leaks.
With the statement int* pointer
you have just defined a pointer but has not allocated any memory. First you should make it point to a proper memory location by allocating some memory like this: int* pointer = new int
. Then in the copy constructor again you have to allocate the memory for the copied object. Also, don't forget to release the memory using delete in the destructor.
I hope this example helps:
class B
{
public:
B();
B(const B& b);
~B();
void setVal(int val);
private:
int* m_p;
};
B::B()
{
//Allocate the memory to hold an int
m_p = new int;
*m_p = 0;
}
B::B(const B& b)
{
//Allocate the memory first
m_p = new int;
//Then copy the value from the passed object
*m_p = *b.m_p;
}
B::~B()
{
//Release the memory allocated
delete m_p;
m_p = NULL;
}
void B::setVal(int val)
{
*m_p = val;
}
I have recently discovered that when I have pointers within a class, I need to specify a Copy constructor.
It is not completely true. When you have pointers in your class and allocate the memory using new
then you have to worry about copy constructor. Also, don't forget the assignment operator and destructor.
You have to delete the memory allocated using delete
.
It's called Law Of The Big Three.
Example:
~Matrix(); //Destructor
Matrix(const Matrix& m); //Copy constructor
Matrix& operator= (const Matrix& m); //Assignment operator
If you want to do a deep copy, you of course must also allocate new memory to hold the values. If the original has a pointer to an int, and you don't want the copy to use the same pointer value, you must allocate new memory to hold an int, and then copy the value there.
Your example is not very clear, it doesn't show the implementation of your copy constructor, or how the pointer
member gets initialized.
if it has a pointer to a regular type then
A::A(const A& a):
pointer_( new int( *a.pointer_ ) )
{
}
if it has a pointer to some base class then
A::A(const &a ):
pointer_( a.pointer_->clone() )
{
}
Clone is a implementation of a prototype pattern
Don't forget to delete the pointer in the destructor
A::~A()
{
delete pointer_;
}
To fix your example
TRY::TRY(TRY const & copyTRY){
int a = *copyTRY.pointer;
pointer = new int(a);
}
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