简体   繁体   中英

Why doesn't CPP create a default deep-copy constructor?

I don't understand why don't they have a copy constructor which makes a real multiple of the original.

As we know the main problem of the default copy constructor is, that it performs a shallow copy. So that if there is a pointer it would only copy it's address but why doesn't it dereference the pointer a copies the content? The main problem arises when having a dinamic allocation of memory. So that one can mistakenly delete it while having a pointer pointing to it, that's why we make our own copy constructors and do not use the default one.

But I can't get it, why doesn't CPP do it? Why doesn't it copy the content

As we know the main problem of the default copy constructor is, that it performs a shallow copy.

We don't know that.

that's why we make our own copy constructors and do not use the default one.

In C++ you should almost never write your own copy constructor ( the rule of zero ).

The main problem arises when having a dinamic allocation of memory. So that one can mistakenly delete it while having a pointer pointing to it

It's a non-problem. Why? Because in C++ we use the concept of RAII and we have tools in the standard library that solved all of the problems you see. In C++ you should never have to write explicit new and you should never have a raw pointer that is a owner. Use standard containers (eg std::vector ) and smart pointers eg ( std::unique_ptr ).

I don't understand why don't they have a copy constructor which makes a real multiple of the original

Because the compiler doesn't know what the copy-semantics of the object should be. That only the writer of the class knows. You can't know what the semantics of the pointer are. Is is a pointer that uniquely owns the memory resource? If so, was it acquired with malloc , new , new[] , or with something else? Does it share its ownership of the memory? Or is it simply pointing to an object it doesn't own? Since you cannot know any of this from the declaration/definition of a class, a compiler simply cannot implement "deep copy" automatically with raw pointers.

Except it does . It does implement deep copy by default, or shallow copy by default, or a combination of them. And it does so correctly. Remember when I told you to not use raw pointers for ownership? Use the appropriate abstractions (containers, smart pointers) and the default copy ctor will do exactly what it needs to do.

As we know the main problem of the default copy constructor is, that it performs a shallow copy.

Shallow copying is not a problem in general. It's only a problem if you want to make a deep copy, have a referential member, and assume the implicit copy constructor to do what you want.

Shallow copying is often useful and typically intentional.

but why doesn't it dereference the pointer a copies the content?

Because where would the copy constructor store the copied object? Where should the pointer member point to?

The compiler cannot read your mind and cannot know whether you want to allocate memory, or how to allocate memory. If the compiler did allocate memory in an implicit function, then who would be responsible for its deletion? If the compiler deleted any pointers implicitly, that would be highly surprising when you intended to have non-owning pointers to something that must not be deleted.

why can't the programmer be responsible for it?

Memory management is difficult enough as it is. At the moment it is at least manageable by following the simple rule: You delete everything that you new . If we introduce implicit allocations and impose the responsibility on the programmer to know of the existence of these implicit allocations, our job would become much harder.

Furthermore, a pointer can have an invalid value. In such cases indirecting through it would have undefined behaviour. And it is impossible to inspect the pointer to find out whether it is invalid. This would make the suggested implicit "deep copying" highly error prone.

Shallow implicit copying is the only sensible choice in a language that has manual memory management. Even in garbage collected languages this is generally the better choice.

that's why we make our own copy constructors and do not use the default one.

We rarely write user declared copy constructors (outside of beginner courses). Those are mostly needed for classes whose sole purpose is to manage memory (or other resources) such as smart pointers. And we rarely need to write those, since the standard library offers the most general smart pointers and data structures out of the box.

we should create our own copy constructor once we have a dynamic memory inside the class

Indeed, if your class manages dynamic memory, then it will need a custom copy constructor. But the typical solution is to not manage dynamic memory inside your class. See the paragraph above. Keep any and all memory allocations and other dynamic resources in a smart pointer or a container.

The compiler has no way of knowing the meaning of the pointers it is supposed to "deep copy".

For example, does a float pointer point to a single float or to a C-style float array? If it is an array, what is the length of the array that it should copy? Please note that I am not talking about C++ style arrays (ie std::array ).

If you want "deep copying" to be handled automatically, you can use container classes for data members that should be copied.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM