Why use copy constructors?

I bought a C++ course on Udemy, and have been brushing up on my C++ and learning all sorts of new things as well. But I dont understand copy constructors, mainly, WHY we use them.

From what I understand, it creates an exact copy of the existing object/objects, but why is this necessary? I understand there are two subsets of this called shallow and deep copying, but my understanding of those is a little muddy, but from doing some research, shallow copying uses the same memory address and references the same objects, whereas deep copying uses separate memory addresses and any changes made to one copy will not reflect in the other

I'm not sure if my explanation of shallow and deep copying are correct, but thats what i've gathered, however I do not understand why we do this.

What would be the application of this in game design? what are some examples I would use copy constructors for? and shallow and deep copy?
But I dont understand copy constructors, mainly, WHY we use them.
From what I understand, it creates an exact copy of the existing object/objects, but why is this necessary?

It's a strange question.
Are you really asking "why would we ever want to copy something"?
Last edited on
well, hmm, how do i explain. I guess not so much why, but some examples of situations that this would be used in and a clearer understanding of whats going on i guess is what i need. I dont quite understand HOW to use it I guess. If I was making a game, what would copy constructors, and shallow and deep copy be used for?
If I was making a game, what would copy constructors [...] be used for?

Again, it a strange question. They would be used to make a copy of the object. What do you think they would be used for?

what would [...] shallow and deep copy be used for?

If the object is a monolithic block of bits like this:

1
2
3
4
struct Block {
    int a, b, c;
    double e, f, g;
};

then a shallow and deep copy are the same. If instead it is made up of different (pointed-to or referred-to) subobjects then the shallow copy only copies those pointers/references and doesn't make an independent copy of the subobjects.

You almost always want a deep copy. If you only get a shallow copy of this:

1
2
3
4
struct Array {
    int*   data;
    size_t size;
};

then you don't really have a copy of the array at all. Any changes to the new array will write to the exact same data as the original. If that's what you want, fine, but it's not generally what's meant by a "copy".

As for when you might actually want a shallow copy, I wouldn't worry about it.
You'll recognize it when you see it (maybe an immutable object, or even a "copy-on-write" optimization).
Last edited on
I wouldn't worry too much about deep copies.
They are not necessary if you don't use raw pointers and it's best pratice to avoid them.
Use STL containers and smart pointers, they implement copy and move operations
1
2
3
4
5
6
7
8
9
class Demo
{
private:
  vector<int> data;
};

Demo d1;
Demo d2(d1); // copy construction
Demo d3 = d1; // copy assignment 

Do you ever call functions? Do you pass arguments to functions by value?
Thanks for the replies guys. I never really use pointers other than references so deep copying isnt something I have to worry about then. I understand whats going on with copying when using functions when you pass by value and reference, so a copy constructor does the exact same thing passing by value does in a function? as in, it just creates a copy and doesnt modify the actual value?

So if I was making a program and I had an enemy, and I wanted to make a copy of it I would use a copy constructor?

The way shallow and deep copying was explained to me is shallow copying can be thought of as an excel sheet that two people are working on on two different computers at the same time, when they both enter their details, the changes will be reflected in the excel sheet, because the same excel sheet is open in both locations, both objects point to the same memory location.

Deep copying was explained like if you copy your friends test, you both will have the exact same test but if you make changes to yours, your friends test will not have those changes, because deep copying allocates separate memory.

Those explanations really made it make sense for me.

So a regular copy constructor performs shallow copying?
Last edited on
Ch1156 wrote:
I understand whats going on with copying when using functions when you pass by value and reference, so a copy constructor does the exact same thing passing by value does in a function? as in, it just creates a copy and doesnt modify the actual value?

Okay, you do assume that copy constructor "does same thing" as passing by value.
What determines, what passing by value does?

(You might see things differently than we do or just call them by different names. Lets see which?)
1
2
3
4
5
6
7
8
9
10
11
12
class T {
  // code
};

void foo( T val ) {
  // code
}

int main() {
  T bar;
  foo( bar );
}

The 'val' is local variable of function foo.
During function call, the 'val' is initialized with value of 'bar'.
How does the system do that initialization?
Maybe I misunderstand the question, I'm unsure. I understand that what's happening is that when bar is passed to food parameters it will not modify whatever values are in foo function because it's being passed by value, instead of by reference. How its initialized I'm unsure, or dont remember.
Lets "inline" the function call:
1
2
3
4
5
6
7
8
9
10
11
class T {
  // code
};

int main() {
  T bar;
  {
    T val( bar );
    // code from foo
  }
}

That similar to what the function call does.
The argument 'val' of foo is copy constructed with the parameter (bar) that foo was called with.

Lets put it other, explicit, way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class T {
  // code
public:
  T() = default;
  T( const T& ) = delete;
};

void foo( T val ) {
  // code
}

int main() {
  T bar;
  foo( bar ); // error
}

 In function 'int main()':
14:12: error: use of deleted function 'T::T(const T&)'
5:3: note: declared here
8:6: error:   initializing argument 1 of 'void foo(T)'

What went wrong?

We told on line 5 that the class T does not need copy constructor.
We told compiler to not create any copy constructor for T.

The result: line 14, function call with by value parameter is not possible, because T does not have copy constructor.

Conclusion: copy constructor is not "like" by value parameter.
To pass parameter by value requires copy constructor.
To pass parameter by value uses copy constructor.


You probably create more copies than you realize.
Do not ask "how to use copy constructor".
The copy constructor is the answer to "What happens when I (attempt to) create a copy?"


Copy assignment is closely related to copy constructor. The difference is that data is copied to already existing object.

Move constructor and move assignment are more recent. Rather than copy, data moves and source object is modified.
Topic archived. No new replies allowed.