Does bitwise copy constructor really share same memory location for objects?

120 Views Asked by At

Hey I am confused regarding memory allocation during bitwise copy of objects in C++. Here's what the book by Herbert Schildt C++ fourth edition Pg:366 says:

Let's begin by restating the problem that the copy constructor is designed to solve. By default, when one object is used to initialize another, C++ performs a bitwise copy. That is, an identical copy of the initializing object is created in the target object. Although this is perfectly adequate for many cases—and generally exactly what you want to happen—there are situations in which a bitwise copy should not be used. One of the most common is when an object allocates memory when it is created. For example, assume a class called MyClass that allocates memory for each object when it is created, and an object A of that class. This means that A has already allocated its memory. Further, assume that A is used to initialize B, as shown here: MyClass B = A;

If a bitwise copy is performed, then B will be an exact copy of A. This means that B will be using the same piece of allocated memory that A is using, instead of allocating its own. Clearly, this is not the desired outcome. For example, if MyClass includes a destructor that frees the memory, then the same piece of memory will be freed twice when A and B are destroyed!

Hence I assumed that if the same piece of memory is used by both A and B , any change made in A should have changes in B object even after memory allocation. So I tried the following code where I have obj1 and obj2 and obj1 is bitwise copied to initialize obj2. However, if the change the private member of obj1 (id) then id of obj2 should also get changed but it doesn't .

Here's the code I've tried:

#include <iostream>
using namespace std;
class Sample {


public:
int id;
void init(int x) {
id = x;
}
void display() {
cout << endl << "ID=" << id;
}
};

int main()
{
Sample obj1;
obj1.init(10);
obj1.display();

// Implicit Copy Constructor Calling
Sample obj2 (obj1);
obj2.display();
cout<<"change"<<endl;
obj1.id=33;
cout<<"value of id inside obj1";
obj1.display();
cout<<" \n value of id inside obj2";
obj2.display();
return 0;

// or obj2 = obj1;

}

And here's the output: output

What is the text book really trying to say ?

2

There are 2 best solutions below

0
Klaus On

You simply have a misunderstanding of the "memory of the object" and the "memory which an object have allocated".

This means that B will be using the same piece of allocated memory that A is using, instead of allocating its own.

This means, if the class A has allocated some memory e.g. with new and holds a pointer to that memory, also class B`s pointer will point to the same memory which was allocated by A. The bitwise copy will only copy the pointer itself and do not automatically allocate new memory and copy the content of the memory pointed to from A also to the memory allocated for B. The last is known as "deep copy".

So please take a look for deep copy and shallow copy. You will find lots of information in the web.

I believe there is no need to write a new extra example in this answer, as there are millions around!

0
Krzysztof Skowronek On

So, I don't really know C++, but I know the answer :)

The issue is external pointers. So, if you class has fields:

class Sample {
   int just_int;
   int * int_pointer;

   sample(){
     int_pointer = new int; // allocation of "external" memory
   }

   ~sample(){
     delete int_pointer;
   }
}

Default copy constructor will correctly copy all the values that are "inside" of you object, so both just_int and int_pointer will be copied.

However, now, two instances of the class will point to the same address in int_pointer member, which will cause problems.

You have to write the copy constructor to copy the memory pointed to by int_pointer - or do whatever is needed according to your needs.

This problem is very common in other programming languages, you can google "deep copy vs shallow copy". Default copy constructor only does "shallow copy", it's on you to make it "deep" if you need it.