DeveloperBreeze

Overview

In C++, copying objects can lead to serious bugs if you're dealing with raw pointers. By default, C++ uses shallow copy, which means only the pointer's value is copied—not the data it points to.

This tutorial covers:

  • What shallow vs deep copy means
  • The problems caused by shallow copy
  • How to implement deep copy correctly
  • A practical class example with dynamic memory
  • When to use Rule of Three vs Rule of Five

What Is Shallow Copy?

A shallow copy copies the values of member variables as-is. If your class has a pointer member, both the original and copy point to the same memory.

class Shallow {
public:
    int* data;

    Shallow(int val) {
        data = new int(val);
    }

    ~Shallow() {
        delete data;
    }
};

Now consider:

Shallow a(10);
Shallow b = a;  // default copy constructor

This causes both a.data and b.data to point to the same memory. When both destructors run, delete is called twice on the same pointer — undefined behavior!


What Is Deep Copy?

A deep copy duplicates the actual data pointed to, not just the pointer.

class Deep {
public:
    int* data;

    Deep(int val) {
        data = new int(val);
    }

    // Copy constructor for deep copy
    Deep(const Deep& other) {
        data = new int(*other.data);
    }

    // Assignment operator for deep copy
    Deep& operator=(const Deep& other) {
        if (this != &other) {
            delete data;
            data = new int(*other.data);
        }
        return *this;
    }

    ~Deep() {
        delete data;
    }
};

Rule of Three

If your class handles dynamic memory:

  • Copy Constructor
  • Copy Assignment Operator
  • Destructor

You must implement all three. This is called the Rule of Three.


Example: Deep Copy for a String Wrapper

class String {
private:
    char* buffer;

public:
    String(const char* str) {
        buffer = new char[strlen(str) + 1];
        strcpy(buffer, str);
    }

    // Copy constructor
    String(const String& other) {
        buffer = new char[strlen(other.buffer) + 1];
        strcpy(buffer, other.buffer);
    }

    // Assignment operator
    String& operator=(const String& other) {
        if (this != &other) {
            delete[] buffer;
            buffer = new char[strlen(other.buffer) + 1];
            strcpy(buffer, other.buffer);
        }
        return *this;
    }

    ~String() {
        delete[] buffer;
    }

    void print() const {
        std::cout << buffer << std::endl;
    }
};

Usage

String a("Hello");
String b = a;       // deep copy
String c("World");
c = a;              // deep assignment

All objects manage their own memory independently.


Modern C++: Rule of Five

In C++11 and newer, also consider:

  • Move Constructor
  • Move Assignment Operator

This is the Rule of Five. Add move semantics if your class is performance-sensitive and uses resource ownership.


Conclusion

When your class uses raw pointers:

  • Avoid shallow copies.
  • Always implement deep copy logic.
  • Follow the Rule of Three (or Rule of Five).
  • Prefer std::string, std::vector, or smart pointers in modern C++.

Understanding deep copy is essential for writing robust, bug-free C++ code.

Continue Reading

Discover more amazing content handpicked just for you

Tutorial

Avoiding Memory Leaks in C++ Without Smart Pointers

Let’s build a small ScopedPointer class.

template <typename T>
class ScopedPointer {
private:
    T* ptr;

public:
    explicit ScopedPointer(T* p = nullptr) : ptr(p) {}

    ~ScopedPointer() {
        delete ptr;
    }

    T& operator*() const { return *ptr; }
    T* operator->() const { return ptr; }
    T* get() const { return ptr; }

    void reset(T* p = nullptr) {
        if (ptr != p) {
            delete ptr;
            ptr = p;
        }
    }

    // Prevent copy
    ScopedPointer(const ScopedPointer&) = delete;
    ScopedPointer& operator=(const ScopedPointer&) = delete;
};

Apr 11, 2025
Read More
Tutorial

Implementing a Domain-Specific Language (DSL) with LLVM and C++

Tools & Libraries:

  • C++ Compiler: A modern C++ compiler with C++17 support (e.g., GCC 10+, Clang 12+).
  • CMake: For building and managing your project.
  • LLVM: Version 15+ (or later). Ensure you have the LLVM libraries and headers installed.
  • Optional: Git for version control and sample project management.

Feb 12, 2025
Read More
Article
javascript

20 Useful Node.js tips to improve your Node.js development skills:

No preview available for this content.

Oct 24, 2024
Read More
Tutorial
javascript

Advanced JavaScript Tutorial for Experienced Developers

In this example, fetchData returns a Promise that resolves after 1 second with a success message. The then method is used to handle the resolved value, and catch is used to handle any errors.

One of the powerful features of Promises is the ability to chain them together, allowing you to perform a sequence of asynchronous operations in a readable manner.

Sep 02, 2024
Read More
Tutorial
bash

Optimizing System Performance with Linux Kernel Parameters

   sudo sysctl -w kernel.sched_min_granularity_ns=10000000
  • kernel.sched_latency_ns:

Aug 19, 2024
Read More
Tutorial
csharp

Developing a Real-Time Multiplayer Game with Unity and C#

  • Save all your changes and go back to the main scene.
  • Press Play and use the NetworkManagerHUD to start as a Host, Client, or Server.
  • You should be able to control the player object and see it move on both the host and client.
  • If your player has animations, you can synchronize them using NetworkAnimator.
  • Add the NetworkAnimator component to your player prefab and link it to the Animator component.

Aug 14, 2024
Read More
Code
csharp

Unity Inventory System using Scriptable Objects

Create a scriptable object for defining item properties.

using UnityEngine;

// Define the base item as a scriptable object
[CreateAssetMenu(fileName = "NewItem", menuName = "Inventory/Item")]
public class Item : ScriptableObject
{
    public string itemName;
    public Sprite icon;
    public bool isStackable;
    public int maxStackSize = 1;

    public virtual void Use()
    {
        Debug.Log($"Using {itemName}");
    }
}

Aug 12, 2024
Read More
Code
csharp

Unity Player Controller Blueprint

No preview available for this content.

Aug 12, 2024
Read More
Code
csharp

Calculate Sum of Numbers in Array

No preview available for this content.

Jan 26, 2024
Read More

Discussion 0

Please sign in to join the discussion.

No comments yet. Start the discussion!