Back to C++
2026-04-126 min read

Copy-initialization (C++)

Learn Copy-initialization (C++) step by step with clear examples and exercises.

Why This Matters

Understanding copy-initialization in C++ is crucial for writing efficient, error-free code. It plays a significant role in creating objects, initializing variables, or passing arguments to functions. Mastering copy-initialization can help you avoid common bugs, improve performance, and prepare better for coding interviews and exams.

Prerequisites

To fully grasp the concept of copy-initialization in C++, you should have a good understanding of:

  1. Basic C++ syntax and data types (int, float, char, etc.)
  2. Declaring variables and creating objects using constructors
  3. Passing arguments by value or reference to functions
  4. Understanding the difference between copy constructor, move constructor, and assignment operator
  5. Familiarity with classes, objects, and member variables
  6. Basic concepts of memory allocation and deallocation in C++
  7. Understanding the concept of shallow vs deep copies
  8. Knowledge of standard template library (STL) containers like std::vector

Core Concept

Copy-initialization in C++ is a method of initializing an object with another object of the same type. The process involves creating a new object and copying the state (values) from the existing object to the newly created one. This can happen during variable declaration, function arguments passing, or return statements.

Syntax

The general syntax for copy-initialization is:

Type variable = existing_object;

Example

Let's consider an example with two Person objects:

#include <iostream>
using namespace std;

class Person {
public:
string name;
int age;

// Constructor
Person(string n, int a) : name(n), age(a) {}
};

int main() {
Person john("John", 25);
Person doe = john;

cout << "John's details: " << endl;
cout << "Name: " << john.name << ", Age: " << john.age << endl;

cout << "\nDoe's details: " << endl;
cout << "Name: " << doe.name << ", Age: " << doe.age << endl;

return 0;
}

In this example, we have a Person class with two properties: name and age. We create an object john using the constructor and then copy-initialize another object doe. When you run this code, both objects will have the same values for their properties.

Worked Example

Let's take a more complex example with a custom class and explore some common pitfalls when using copy-initialization:

#include <iostream>
using namespace std;

class Car {
public:
string brand;
int year;
double mileage;

// Constructor
Car(string b, int y, double m) : brand(b), year(y), mileage(m) {}
};

void printCarDetails(const Car& car) {
cout << "Brand: " << car.brand << ", Year: " << car.year << ", Mileage: " << car.mileage << endl;
}

int main() {
Car myCar("Toyota", 2015, 60000);
Car yourCar = myCar; // Copy-initialization

cout << "\nMy Car Details:" << endl;
printCarDetails(myCar);

cout << "\nYour Car Details:" << endl;
printCarDetails(yourCar);

// Shallow copy issues
yourCar.mileage += 10000; // This will also increase myCar's mileage because they share the same memory location

return 0;
}

In this example, we have a Car class with three properties: brand, year, and mileage. We create an object myCar using the constructor and then copy-initialize another object yourCar. The printCarDetails() function takes a constant reference to a Car object as an argument.

When you run this code, both objects will have the same values for their properties. However, if you modify any property of either object, the changes will affect both objects because they share the same memory location. This is known as shallow copy.

Deep Copy

To avoid shallow copy issues, we can implement a deep copy constructor that creates a new object with its own memory allocation for each property:

Car(const Car& other) : brand(other.brand), year(other.year), mileage(other.mileage) {}

Now, when you modify any property of either object, the changes will not affect the other object because they have separate memory locations for their properties:

yourCar.mileage += 10000; // This will only increase yourCar's mileage and leave myCar's mileage unchanged

Common Mistakes

  1. ### Forgetting the = operator

When initializing an object with another object of the same type, you must use the = operator:

// Incorrect
Person doe(john); // This creates a new object but does not copy john's properties

// Correct
Person doe = john; // This copies john's properties to a new object
  1. ### Assigning objects of different types

Copy-initialization only works with the same type of objects:

// Incorrect
int i = 5;
float f = i; // This will result in a compile error
  1. ### Ignoring shallow copy issues

When using copy-initialization, be aware that the default implementation creates a shallow copy, which means both objects share the same memory location for their properties. This can lead to unexpected behavior when modifying one object affecting the other:

// Incorrect
Car myCar("Toyota", 2015, 60000);
Car yourCar = myCar;

yourCar.mileage += 10000; // This will also increase myCar's mileage because they share the same memory location
  1. ### Using copy-initialization for arrays of objects

Copy-initialization cannot be directly used to initialize an array of objects:

// Incorrect
Person people[] = {john, doe}; // This will result in a compile error

To solve this issue, you can create an array of objects and then copy-initialize each element individually or use a container like std::vector.

  1. ### Forgetting to implement deep copy constructor for custom classes

When using custom classes with properties that contain pointers or other expensive-to-copy data types, it's essential to implement a deep copy constructor to avoid shallow copy issues:

class ComplexNumber {
public:
double real;
double imag;

// Shallow copy constructor
ComplexNumber(const ComplexNumber& other) : real(other.real), imag(other.imag) {}

// Deep copy constructor
ComplexNumber(const ComplexNumber& other) {
real = other.real;
imag = other.imag;
}
};

Practice Questions

  1. Write a Rectangle class with properties width and height. Implement a copy constructor that copies the properties from one rectangle to another.
  2. Given the following code:
int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr;
int brr[] = {6, 7, 8, 9, 10};
int* bptr = brr;

*ptr++ = *bptr++; // This line of code is doing what operation?

Explain the operation being performed.

  1. Implement a deep copy constructor for the Car class from the worked example to avoid shallow copy issues.
  2. Write a custom assignment operator for the Person class that performs a deep copy instead of a shallow copy when assigning one object to another.
  3. Create a Student class with properties name, age, and GPA. Implement a copy constructor, move constructor, and assignment operator for this class.
  4. Explain the difference between copy-initialization, copy assignment, and move construction in C++. Provide examples of when each would be used.

FAQ

### What is the difference between copy-initialization and assignment operator?

Copy-initialization is used during variable declaration or function arguments passing, while the assignment operator (=) is used to assign a value to an existing object.

### Why do we need a deep copy constructor for custom classes?

A deep copy constructor creates a new object with its own memory allocation for each property, avoiding the shallow copy issues that can occur when modifying one object affects another.

### Can I use copy-initialization to initialize an array of objects?

No, you cannot directly use copy-initialization to initialize an array of objects. You can create an array of objects and then copy-initialize each element individually or use a container like std::vector.

### What is the difference between shallow copy and deep copy in C++?

Shallow copy creates new objects with the same memory addresses for their properties, while deep copy creates new objects with separate memory allocations for their properties. This helps to avoid unexpected behavior when modifying one object affecting another.

### What is move construction in C++ and when would it be used?

Move construction is a process of creating an object by taking ownership of the resources from an existing object (usually temporary or rvalue) without copying its state. It is useful when you have expensive-to-copy objects, such as large containers, and want to avoid unnecessary copies.

Copy-initialization (C++) | C++ | XQA Learn