Friday, April 4, 2014

Deep copy and shallow copy in C++

Problem
Write a method that takes a pointer to a Node structure as a parameter and returns a complete copy of the passed-in data structure. The Node structure contains two pointers to other Node structures.
Solution

A shallow copy copies the array and maintains references or copies address to the original objects.

A deep copy will copy (clone) the objects too so they bear no relation to the original. Implicit in this is that the object themselves are deep copied. This is where it gets hard because there's no real way to know if something was deep copied or not.

The copy constructor is used to initilize the new object with the previously created object of the same class. By default compiler wrote a shallow copy.

Example
Consider the class X below. Note that pi in the class below is a reference, and hence simple copy will result in shallow copy. Consider the copy constructor of X, where pi is copied in a shallow way.

class X
{
 private:
  int i;
  int *pi;
 public:
  X()
   : pi(new int)
  { }
  X(const X& copy)   // copy ctor
   : i(copy.i), pi(copy.pi)
  { }
};

Now lets copy pi in the deep way:
class X
{
 private:
  int i;
  int *pi;
 public:
  X()
   : pi(new int)
  { }
  X(const X& copy)   // copy ctor
   : i(copy.i), pi(new int(*copy.pi))  // note this line in particular!
  { }
};

As you must have noticed, whether copy constructor copies in a shallow and deep way is implementation - dependent. This means that there are no strict rules about that, you can implement it like a deep copy or shallow copy, however as far as i know it is a common practice to implement a deep copy in a copy constructor. A default copy constructor performs a shallow copy though.


Shallow copy works fine when dynamic memory allocation is not involved because when dynamic memory allocation is involved then both objects will points towards the same memory location in a heap, Therefore to remove this problem we wrote deep copy so both objects have their own copy of attributes in a memory.

When you want to do some operations on the object but you don’t want to change it, you use deep copy. Otherwise, you use shallow copy.
struct Test {
    char * ptr;
};
 
void shallow_copy(Test & src, Test & dest) {
    dest.ptr = src.ptr;
}
 
void deep_copy(Test & src, Test & dest) {
    dest.ptr = malloc(strlen(src.ptr) + 1)
    memcpy(dest.ptr, src.ptr);
}

Note that shallow_copy may cause a lot of programming run-time errors, especially with the creation and deletion of objects. Shallow copy should be used very carefully and only when a programmer really understands what he wants to do. In most cases shallow copy is used when there is a need to pass information about a complex structure without actual duplication of data (e.g., call by reference). One must also be careful with destruction of shallow copy.
In real life, shallow copy is rarely used. There is an important programming concept called "smart pointer" that, in some sense, is an enhancement of the shallow copy concept.
Deep copy should be used in most cases, especially when the size of the copied structure is small.

References
http://tianrunhe.wordpress.com/2012/04/14/deep-copy-structure-of-pointers-in-c/
http://stackoverflow.com/questions/2657810/deep-copy-vs-shallow-copy

0 comments:

Post a Comment