The 4 terms:
- memberwise copy
- bitwise copy
- shallow copy
- deep copy
do not exist on the same axis of meaning.
The Deep Copy is what most people, in most circumstances, would expect from a semantic object in programming when they say: "Computer, give me a copy".
Specifically, in the context of C++, it would mean that the copy of an existing object has also recursively copied all sub-objects, no matter how they are implemented. (Pointers, int
s, other complex objects, ...)
The Shallow Copy is what you get when you do not take into account that some direct in-memory members of an object are in fact pointers (of some sort) and you only copy their "pointer value" instead of following the indirection and creating proper copies of the pointed-to objects as well.
Shallow Copy is what you get in C++ when the compiler does a naive memberwise copy (see below) and your object contains (raw) pointers. Shallow copy is also what you get in Java or C# if you do a naive copy of any object, because there, "everything" is a pointer/reference.
If you have a trivially copyable object, e.g. a struct
containing only int
s then a shallow copy is the same as a deep copy.
The Bitwise Copy is what you get in C++ when you do a memcpy()
of an in-memory object. The result may be a Deep copy semantically, or (more likely) a Shallow Copy (if pointers involved) or it may result in just a bunch of bits in memory that are no longer of the form of a valid object of the type being copied from.
Finally, the Memberwise Copy is, within C++, a specific term called out by the C++ Std for what a compiler generated copy C'tor will do when being invoked. Specifically:
The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members. (...)
in [class.copy.ctor]
and it goes on to describe what that means:
Each base or non-static data member is copied/moved in the manner appropriate to its type: (...)
(!!) A Memberwise Copy can be semantically equivalent to all of the 3 types above, depending on the object.
(I note at this point that the C++ Std always uses "memberwise", never "member-wise", but my auto correction prefers "member-wise" or "member wise" -- this may help when googling.)
As far as I'm concerned, if you have a user-defined copy ctor, you never (should) see 1:1 memberwise copy, because if you do 1:1 memberwise copy you do not need to implement the ctor, the compiler will generate it for you anyway.
To make a few comparisons:
- If you have a
struct
of int
s, then a memberwise copy results in the same thing as a bitwise copy, and it is a shallow copy as well as a deep copy (well, there ain't no depth t speak of).
- If you have a
struct
of int*
pointers, than a memberwise copy is the same as a bitwise copy, and it is also a shallow copy, but it is no longer a deep copy, because the copy will point to the same integers as the original.
- If you have a struct containing any non-trivial object (e.g. a
std::string
), then a bitwise copy is no longer valid, and whether a memberwise copy is shallow or deep depends on the implementation of the sub-objects: If the subobjects all implement deep-copy on copy construction, the the copy is deep. If you have any subobject member that only does shallow copies, then the memberwise copy will also be (partially) shallow.