Skip to main content

Shallow Copy & Deep Copy in C++

Certainly! Exploring the concepts of shallow and deep copying in C++ is essential for understanding how objects are duplicated. Let's delve into these topics with comprehensive explanations and illustrative examples to clarify their differences and uses.

Shallow Copy

A shallow copy of an object copies all the member field values. This works fine if the object contains only primitive data types. However, if the object contains pointers to dynamically allocated memory, the shallow copy will copy the pointer values, not the actual data they point to. This means both the original and the copied object will point to the same memory location, which can lead to issues like double deletion or unintended modifications.

Example of Shallow Copy

#include <iostream>
using namespace std;

class Box {
private:
    int length;
    int breadth;
    int height;
    int *p;

public:
    // Function that sets the dimensions
    void set_dimensions(int length1, int breadth1, int height1, int x) {
        length = length1;
        breadth = breadth1;
        height = height1;
        p = new int;
        *p = x;
    }

    // Function to display the dimensions
    void show_data() {
        cout << "Length = " << length << "\nBreadth = " << breadth << "\nHeight = " << height << "\nP int pointing to = " << *p << endl;
    }
};

int main() {
    Box B1, B3;
    B1.set_dimensions(14, 12, 16, 100);
    B1.show_data();

    // Shallow copy using copy constructor
    Box B2 = B1;
    B2.show_data();

    // Shallow copy using assignment operator
    B3 = B1;
    B3.show_data();

    return 0;
}

In this example, B2 and B3 are shallow copies of B1. The pointer p in B2 and B3 will point to the same memory location as in B1. Any change in the value pointed out by p in one object will reflect in the other objects.


Deep Copy

A deep copy, on the other hand, creates a new copy of the dynamically allocated memory as well. This ensures that the copied object has its own separate copy of the data, preventing issues related to shared memory.

Example of Deep Copy

#include <iostream>
using namespace std;

class Box {
private:
    int length;
    int breadth;
    int height;
    int *p;

public:
    // Constructor
    Box() {
        p = new int;
    }

    // Copy constructor for deep copy
    Box(const Box &obj) {
        length = obj.length;
        breadth = obj.breadth;
        height = obj.height;
        p = new int;
        *p = *(obj.p);
    }

    // Function that sets the dimensions
    void set_dimensions(int length1, int breadth1, int height1, int x) {
        length = length1;
        breadth = breadth1;
        height = height1;
        *p = x;
    }

    // Function to display the dimensions
    void show_data() {
        cout << "Length = " << length << "\nBreadth = " << breadth << "\nHeight = " << height << "\nP int pointing to = " << *p << endl;
    }

    // Destructor
    ~Box() {
        delete p;
    }
};

int main() {
    Box B1;
    B1.set_dimensions(14, 12, 16, 100);
    B1.show_data();

    // Deep copy using copy constructor
    Box B2 = B1;
    B2.show_data();

    return 0;
}

In this example, the copy constructor creates a new memory location for the pointer p and copies the value from the original object. This ensures that B2 it has its own copy of the data, independent of B1.

Key Differences

  • Shallow Copy: Copies the values of the data members as they are, including pointers, which means both objects share the same memory location for dynamically allocated data.
  • Deep Copy: Allocates separate memory for the pointers and copies the actual data, ensuring that the copied object has its own independent copy of the data.


Do you have any specific scenarios or further questions about shallow and deep copying in C++?

Comments

Popular posts from this blog

Understanding push_back and emplace_back in C++

| Understanding push_back and emplace_back in C++ C++ provides several mechanisms to add elements to its containers, and two often used are push_back and emplace_back . Understanding the difference between these methods can help you write more efficient and expressive code. Let's delve into these concepts with examples to illustrate their usage and benefits.

constexpr in C++

|  Let’s dive into the depths of constexpr in C++! constexpr is short for "constant expression." It was introduced in C++11 and further enhanced in C++14 and C++20. The primary purpose of constexpr is to allow the evaluation of expressions at compile-time, enabling several powerful optimizations. Here’s a detailed breakdown: Purpose of constexpr The idea behind constexpr  is to inform the compiler that the value of a variable or the result of a function can be determined at compile-time. It will be if the expression can be evaluated at compile-time, resulting in performance benefits. It’s beneficial for: - Compile-time constants: Values that don’t change at runtime. - Optimizations: Allowing the compiler to optimize code more effectively. - Template metaprogramming: Enhancing the power of templates. Usage in Variables A constexpr  variable must be initialized with a constant expression.  Here’s an example: constexpr int length = 10; constexpr int width = 5; conste...

When do we use Initializer List in C++?

An initializer list is used to initialize the data members of a class. This list of members to be initialized is specified in the constructor as a comma-separated list, followed by a colon. Here is an example that demonstrates the use of an initializer list to initialize the variables x and y in the Point class. #include<iostream>  using namespace std;     class Point {  private:      int x;      int y;  public:      Point(int i = 0, int j = 0):x(i), y(j) {}       /*  The above use of the Initializer list is optional as the           constructor can also be written as:          Point(int i = 0, int j = 0) {              x = i;              y = j;          }      */              ...