Fundamentals 31 min read

When Does C++ Generate a Default Copy Constructor? A Deep Dive

This article explains the role of copy constructors in C++, when the compiler automatically provides a default one, the situations that trigger copy construction, why bitwise copying can be unsafe, and how to implement proper deep‑copy semantics with clear code examples.

Deepin Linux
Deepin Linux
Deepin Linux
When Does C++ Generate a Default Copy Constructor? A Deep Dive

What Is a Copy Constructor?

In C++, a copy constructor is a special constructor whose parameter is a reference to an object of the same class; it initializes a new object using an existing one, typically declared as ClassName(const ClassName& other).

When Is a Copy Constructor Invoked?

Object initialization: MyClass obj2 = obj1; creates obj2 as a copy of obj1.

Function parameter passing by value: a copy is made for the parameter object.

Function return by value: the returned object is copied to the caller. void myFunction(MyClass obj) { /* ... */ } Calling myFunction(existingObj) triggers the copy constructor for obj.

Scenarios Where Bitwise Copy Fails

1. Member objects with custom copy behavior

If a class contains a member such as std::string that defines its own copy constructor, the default copy constructor will correctly delegate to that member’s copy constructor, performing a deep copy.

2. Inheritance from a base class with a copy constructor

Derived classes automatically invoke the base class’s copy constructor; failing to do so can leave the base part uninitialized.

3. Classes with virtual functions

Objects with virtual functions contain a virtual‑function table pointer (vptr). The default copy constructor copies this pointer so that the copied object preserves the correct dynamic type.

4. Virtual inheritance

When a class participates in virtual inheritance, the compiler‑generated copy constructor copies the virtual‑base‑table pointer to maintain the shared base subobject.

When Does the Compiler Generate a Default Copy Constructor?

If the class has member objects whose types provide copy constructors.

If the class participates in inheritance (base class has a copy constructor).

If the class declares virtual functions.

If the class uses virtual inheritance.

In all these cases, the compiler synthesizes a copy constructor that performs member‑wise copying, invoking copy constructors of subobjects as needed.

Common Pitfalls of the Default (Shallow) Copy

The default copy constructor performs a shallow copy, merely copying pointer values. For a class managing dynamic memory, such as:

class MyString {
    char* str;
public:
    MyString(const char* s) {
        str = new char[std::strlen(s) + 1];
        std::strcpy(str, s);
    }
    ~MyString() { delete[] str; }
};

Copying MyString s2 = s1; makes s2.str point to the same memory as s1.str, leading to double‑free, dangling pointers, and unintended data sharing.

Implementing a Deep Copy Constructor

To avoid these issues, define a custom copy constructor that allocates its own resources and copies the contents:

class MyString {
    char* str;
    int length;
public:
    MyString(const char* s) {
        length = std::strlen(s);
        str = new char[length + 1];
        std::strcpy(str, s);
    }
    // Deep copy constructor
    MyString(const MyString& other) {
        length = other.length;
        str = new char[length + 1];
        std::strcpy(str, other.str);
    }
    ~MyString() { delete[] str; }
};

This ensures each object owns independent memory, preventing double deletion and data‑corruption problems.

Key Takeaways

The default copy constructor is generated only when needed and performs member‑wise copying.

Bitwise copying is safe for simple POD types but unsafe for classes managing resources.

When a class contains pointers, dynamic allocations, or participates in complex inheritance, a custom deep‑copy constructor (and often a custom assignment operator) is required.

C++deep copyInheritanceshallow copyobject copyingCopy ConstructorDefault Constructor
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.