6

Does the default copy-constructor do a shallow or a deep copy in C++?

I am really confused with default copy constructor in cpp, as it does shallow copy or deep copy, as when I did v2=v1; suppose v1={1,2,3}, now if I have done v2[0]=1; It does not get reflected but I heard it does shallow copy, can anybody please explain?

Jason
  • 36,170
  • 5
  • 26
  • 60
  • 1
    Please provide a [mcve], we have no idea how your class looks like – UnholySheep Jul 18 '18 at 15:42
  • 4
    C++ really doesn't have the concept of deep or shallow copies, just the concept of semantically correct copies for a particular class. –  Jul 18 '18 at 15:43
  • 1
    @NeilButterworth Unless academia steps in. Then all bets are off. – Ron Jul 18 '18 at 15:47
  • The default copy constructor copies the contents of variables, nothing more, nothing less. If you have a copy constructor, then the code in the copy constructor is executed. – Thomas Matthews Jul 18 '18 at 15:58
  • Tightly related: [What is the Rule of Three?](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – user4581301 Jul 18 '18 at 16:09
  • More details on how `{1,2,3}` is being stored in `v1` is required to provide a complete answer. – user4581301 Jul 18 '18 at 16:14

3 Answers3

8

It doesn't do either. It does a memberwise copy. I.e. it copies all the members of the class using their copy constructors. If those members have copy constructors that do a deep copy then you'll get a deep copy, if they do a shallow copy then you'll get a shallow copy, or they could do something else entirely.

Deep copy and shallow copy are not C++ concepts, instead C++ lets you do a deep or shallow copy as you prefer.

john
  • 85,011
  • 4
  • 57
  • 81
  • 3
    Note that this means if your class contains a pointer, the pointer and only the pointer is copied. You now have two objects pointing to the same thing. Depending on the ownership of this pointed-at thing, this may be bad. – user4581301 Jul 18 '18 at 16:11
  • A _memberwise_ copy **is** a shallow copy. A “deep” copy is one where the container object knows stuff about how to properly duplicate its referenced field objects. – Dúthomhas Oct 28 '22 at 15:27
3

Your question is the wrong question.

First, C++ default copy/assign is memberwise; it recursively copies/assigns based on what the members do.

Well designed C++ types follow a few patterns in what they do when copied/assigned that lines up with 3 different kinds of primitive types; value, reference amd pointer semantics.

A value semantics type behaves like a value. This corresponds to your "deep copy" roughly. Modifying one variable that follows value semantics never changes another. std::vector is a value semantics type, as is int, double, std::string and other std container types. Value semantics are a strong pattern, and make reasoning about program behaviour easy. Note that value semantics need not be implemented as values; vector is typically implemented as a triple of pointers, with construction/copying/etc overloaded.

A reference semantics type behaves like a C++ reference type -- int&. This is not the same as a Java/C# reference. C++ references are aliases; int& a=b; means a is another name for b. Then a=7 makes both a and b equal 7. If you had another reference c, a=c would not rebind a to refer to c; it would change what a referred to to have the same value as what c referred to.

Complex objects with reference semantics are rare.

A pointer semantics is like reference semantics, but assignment rebinds who it points to. Sometimes an additional operation, like &, is needed to create a new pointer. A type with pointer semantics includes std::reference_wrapper, std::string_view, std::shared_ptr<double>, gsl::span<char> and int*.

Typically it is a bad idea to mix members with different semantics in the same type; the rule of 0/3/5 states that the best move/copy/assogn/ctor/dtor is the empty one. Your resource management types use RAII and write those special members, the other types aggregate them. Value semantics types are not used mixed with reference/pointer in order for the composite class to get coherant semantics.

TL;DR: it depends. Read the documentation on your members. Document what semantics your types have so users know what to expect.

Note, however, that reference semantics is incompatible with being stored in a std container.

user4581301
  • 33,082
  • 7
  • 33
  • 54
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

The implicitly generated copy constructor (and assignment operator) performs a shallow copy.

There is no difference between a shallow copy, and deep copy of a value type.

now if I have done v2[0]=1; It does not get reflected

There is no reason to expect such operation to get reflected unless the type of v2 is a referential type.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • This was probably downvoted because it is unclear to someone unused to C++'s ability to have complex objects with value semantics. To improve I'd advise elaborating about value/reference (and pointer) semantics, how member semantics impacts default semantics of a type, and how that flows back into deep/shallow conxept. Because everything you said is true, but I suspect not useful to the OP as written. Meh, maybe I'll just answer. – Yakk - Adam Nevraumont Jul 18 '18 at 16:25
  • You said "There is no difference between a shallow copy, and deep copy of a value type", what does it mean? as they share the same memory (shallow copy) as this is the assignment operator. – Robin Khurana Jul 18 '18 at 17:38
  • @RobinKhurana It means that there is only one kind of copying of value types - there is no distinction between shallow and deep copy for them. `as they share the same memory` What share the same memory? – eerorika Jul 18 '18 at 17:42